研1 上 隨筆
第三周
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv1 = nn.Conv2d(3, 16, 5)
self.pool1 = nn.MaxPool2d(2, 2) # 此處dilation=1默認
self.conv2 = nn.Conv2d(16, 32, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(32*5*5, 120) #全連接
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x): #[batch, channel, height, width]
x = F.relu(self.conv1(x)) # input(3, 32, 32) output(16, 28, 28)
# N = (W-F+2P)/S+1 = (32-5+0)/1 + 1 = 28
x = self.pool1(x) # output(16, 14, 14)
x = F.relu(self.conv2(x)) # output(32, 10, 10)
x = self.pool2(x) # output(32, 5, 5)
# print(x.size()) # torch.Size([36, 32, 5, 5])
# [batch, channel, height, width]
x = x.view(-1, 32*5*5) # output(32*5*5) "-1"電腦幫我們算
#也可寫成x = x.view(36, 32*5*5) 或者 10000 #每個批次都展平
x = F.relu(self.fc1(x)) # output(120)
x = F.relu(self.fc2(x)) # output(84)
x = self.fc3(x) # output(10)
return x
Pytorch Tensor 的通道排序:[batch, channel, height, width]
4行到10行代碼:
nn.MaxPool2d
torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
步幅和池化窗口大小相同,避免堆疊.(實際上池化是否有重疊,不重要)
dilation=1,默認不空格,注意: 不要和孔卷積混淆
張量拼接
X = torch.cat((X, X + 1), 1) #cat維度不變
池化層 作用
-
1 減少計算量
-
2 讓卷積對位置沒有那么敏感
池化為什么越用越少
-
1 用卷積層 + stride = 池化層減少位置敏感
-
2 對數據本身做增強:位移、放大、旋轉,消除位置敏感,讓卷積不會過擬合
nn.Conv2d
-
卷積層將輸入和矩陣斤行交叉相關,加上偏移后得到輸出
-
卷積核和偏移是可學習的參數
-
卷積核的大小是超參數
torch.view() & torch.reshape()
view能干的reshape都能干,如果view不能干就可以用reshape來處理
x = x.view(-1, 32*5*5) # output(32*5*5) "-1"電腦幫我們算,也可寫成x = x.view(36, 32*5*5) 或者 10000 #每個批次都展平
參考Test1_offical_demo -> model.py -> 44Line
第五周
torch.unsqueeze()
a = torch.unsqueeze(a, dim=0) # 增加一個維度,在第0維
>>> import torch
>>> a = torch.arange(0, 6)
>>> print(a.shape)
torch.Size([6])
>>> a = torch.unsqueeze(a, 0)
>>> print(a.shape)
torch.Size([1, 6])
>>> print(a)
tensor([[0, 1, 2, 3, 4, 5]])
torch.flatten()
將tensor展平
x = torch.flatten(x, start_dim=1) #因為[banch, channal, 高度, 寬度],所以從第一個維度開始展開,0維banch不動
也可以使用前面的torch.view()來將tensor展平(參考Test2_alexnet -> model.py -> 38Line)
nn.Sequential
Sequential能把一系列操作打包
self.features = nn.Sequential(
nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
調用GPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
回顧卷積后矩陣尺寸大小計算公式
N = (W - F + 2P) / S + 1
- 輸入圖片大小 W * W
- Filter大小 F * F
- 步長s
- padding的像素數P
如果結果不能整除,則舍去余數的那幾行
回顧python相對路徑
“/”:表示根目錄,在windows系統下表示某個盤的根目錄,如“E:\”;
“./”:表示當前目錄;(表示當前目錄時,也可以去掉“./”,直接寫文件名或者下級目錄)
“../”:表示上級目錄。
AlexNet
過擬合:
-
特征維度過多
-
模型假設過於復雜
-
參數過多
-
訓練數據過少、噪聲過多
過擬合造成的后果
函數能完美的預測訓練姐,但對新數據的測試集預測較差
過度擬合訓練數據,而沒有考慮泛化能力。
AlexNet的做法
使用Dropout的方式在網絡正向傳播過程中隨機失活一部分神經元(變相減少了訓練參數,從而減少了過擬合)
AlexNet的結構
layer_name | kernel_size | kernel_num | padding | stride |
---|---|---|---|---|
Conv1 | 11 | 96 | [1, 2] | 4 |
Maxpool1 | 3 | None | 0 | 2 |
Conv2 | 5 | 256 | [2, 2] | 1 |
Maxpool2 | 3 | None | 0 | 2 |
Conv3 | 3 | 384 | [1, 1] | 1 |
Conv4 | 3 | 384 | [1, 1] | 1 |
Conv5 | 3 | 256 | [1, 1] | 1 |
Maxpool3 | 3 | None | 0 | 2 |
FC1 | 2048 | None | None | None |
FC2 | 2048 | None | None | None |
FC3 | 1000 | None | None | None |
GoogleNet
深度上 的拼接
ResNet殘差網絡
通過堆殘差網絡,達到
- 解決梯度消失、梯度爆炸
- 退化問題(degradation problem)
主分支和側分支(sortcut 捷徑)的輸出矩陣shape必須相同,
相同維度位置上的相加
第八周
BatchNormalization(批標准化)
self.conv1 = nn.Conv2d(64, 64, 3, padding=1)
self.bn1 = nn.BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True)
self.relu1 = nn.ReLU(inplace=True)
順序:卷積 --> 批標准化 --> relu
Concatenation操作
將新向量拼接到原來的向量之后,對應着維數增加
http://wap.sciencenet.cn/blog-3428464-1250954.html?mobile=1
注意力機制代碼實現
x3 = self.rfb2_1(h_nopool3) # rfb3_1
att_3 = self.att_1(x3)
x3 = x3 * F.sigmoid(att_3)
x4 = self.rfb3_1(h_nopool4) # rfb4_1
att_4 = self.att_2(x4)
x4 = x4 * F.sigmoid(att_4) #有些注意力機制還要再額外加上自身
x5 = self.rfb4_1(h) # rfb5_1
att_5 = self.att_3(x5)
x5 = x5 * F.sigmoid(att_5)
detection_map = self.agg1(x5, x4, x3)
self.att_1 = nn.Conv2d(32, 1, 3, padding=1)
self.att_2 = nn.Conv2d(32, 1, 3, padding=1)
self.att_3 = nn.Conv2d(32, 1, 3, padding=1)
self.agg1 = aggregation_add(channel)
疑問:為何監督時引入雜質反而性能更優?
下周任務(A2dele代碼調整:直接將λ的值設置成0,嘗試復現消融實驗)
\(L_{Adap}=λL_{KL}(S_{RGB}||S_{depth})+(1-λ)L_{CE}(S_{RGB},Y)\)
YOLO標簽過少(樣本不均衡)問題
-
使用展示台旋轉拍照
-
使用視頻軟件截圖
-
使用遷移學習,遷移 "燈" ==> "開關"(不現實)
-
或者 直接使用方框打標,再進行修改(正在實現)
conda中安裝cuda + cudnn + apex踩坑
安裝cuda
不僅僅要在虛擬環境里面安裝 cuda,物理機里也要安裝同樣版本的cuda,否則apex無法工作。
歷史版本cuda下載https://developer.nvidia.com/cuda-toolkit-archive
歷史版本cudnnhttps://developer.nvidia.com/rdp/cudnn-archive#a-collapse742-10
安裝apex
https://github.com/NVIDIA/apex/issues/802#issuecomment-618699214
apex會報奇奇怪怪的錯誤,其中大概率是由於最新版apex引入了不兼容的東西
使用以下git語句倒回apex的之前版本
git checkout f3a960f80244cf9e80558ab30f7f7e8cbf03c0a0
使用apex
try: # Mixed precision training https://github.com/NVIDIA/apex
from apex import amp
except:
print('Apex recommended for faster mixed precision training: https://github.com/NVIDIA/apex')
mixed_precision = False
if mixed_precision:
model, optimizer = amp.initialize(model, optimizer, opt_level='O1', verbosity=0)
if mixed_precision:
with amp.scale_loss(loss, optimizer) as scaled_loss:
scaled_loss.backward()
else:
loss.backward()
使用apex的風險
使用半精度的優化訓練可能會造成訓練效果差的情況
a、混合精度訓練
b、損失放大
Error:container_abcs
ImportError: cannot import name 'container_abcs' from 'torch._six'
因為1.8版本之后container_abcs就已經被移除了。
解決方法如下
#if TORCH_MAJOR == 0:
import collections.abc as container_abcs
# else:
# from torch._six import container_abcs
P2 pycococtools
P2 pycococtools的安裝包https://pan.baidu.com/s/1nWQdPRtGwNnOO2DkxRuGuA提取碼:i5d7 安裝完直接解壓復制其中pycocotools兩個文件夾到conda環境…\Lib\site-packages之中
yolov3踩坑
voc_label.py make_txt.py
打標的文件夾、圖片千萬不能有中文,否則要用軟件調整很久
yolov3-tiny.cfg
修改類別需要修改四個地方:兩個filters,兩個classes(127、135、171、177)
https://blog.csdn.net/qq_33728095/article/details/116331714
第九周
解決PyCharm無法自動上傳到遠端服務器的bug
選擇遠程python解釋器的同時,修改同步文件夾(不要使用默認分配的tmp文件夾,容易同步失敗)
遠程運行所生成的文件需要手動同步到本地。
完全卸載Anaconda
需要先在anaconda中執行命令
conda install anaconda-clean
anaconda-clean --yes
再到文件夾運行uninstall Anaconda3
conda安裝onnx
conda install -c conda-forge onnx
conda install -c conda-forge onnxruntime
下載緩慢,可以訪問
https://anaconda.org/conda-forge/onnx/files?version=1.8.1
手動下載,然后
conda install --use-local onnx-1.8.1-py36h6d34f3e_0.tar.bz2
貌似沒啥用的更新語句
但是能解決上面onnx安裝不成功的問題(onnxruntime解決不了)
conda install conda
conda update --all
YOLOX
https://github.com/Megvii-BaseDetection/YOLOX
批量刪除、替換文件中的字符串
import re
import os
s = os.sep
root = "Annotations/"
for i in os.listdir(root):
if os.path.isfile(os.path.join(root,i)):
print(i)
filePath = os.path.join(root,i)
a= open(filePath,'r') #打開所有文件
str = a.read()
str = str.replace('S_OFF ','S_OFF') #將字符串里前面全部替換為后面
print(os.path.join(root,i))
print(str)
b = open(filePath,'w')
b.write(str) #再寫入
b.close() #關閉文件
30系列顯卡環境配置
30系顯卡由於框架更新不可使用requirements.txt的配置。
可以用的30顯卡配置如下: pytorch代碼對應的pytorch版本為1.7.0,cuda為11.0,cudnn為8.0.5。
YOLOV5
https://github.com/ultralytics/yolov5
需要修改的文件:
voc.yaml
yolov5s.yaml
train.py
parser.add_argument('--weights', type=str, default=ROOT / 'yolov5s.pt', help='initial weights path')
parser.add_argument('--cfg', type=str, default='models/yolov5s.yaml', help='model.yaml path')
parser.add_argument('--data', type=str, default=ROOT / 'data/physics.yaml', help='dataset.yaml path')
將圖片多線程載入內存(過多的線程可能會造成“慢啟動”現象,夠用就行)
parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')
batch-size和epochs的修改
datasets.py:第81行里面的參數nw改成0
#num_workers=nw
num_workers=0
tensorbord
使用yolo v5自帶的
tensorboard --logdir runs\train
按照提示訪問所在鏈接
第十周
化學標注轉yoloLable代碼
import os;
list = ['鐵夾橫梁', '手', '渾濁石灰水', '燒杯', '固體葯品', '固體瓶', '液體瓶', '直立無導管集氣瓶', '手拿瓶', '倒放瓶塞', '直立有導管集氣瓶', '清澈石灰水', '火焰', '正放瓶塞']
def reset():
i = 0
path = r"VOCdevkit/VOC2007/YOLO/";
filelist = os.listdir(path) # 該文件夾下所有的文件(包括文件夾)
for files in filelist: # 遍歷所有文件
i = i + 1
Olddir = os.path.join(path, files); # 原來的文件路徑
if os.path.isdir(Olddir): # 如果是文件夾則跳過
continue;
filename = os.path.splitext(files)[0]; # 文件名
filetype = os.path.splitext(files)[1]; # 文件擴展名
filePath = path + filename + filetype
alter(filePath, "/art/", "../art/")
def alter(file, old_str, new_str):
with open(file, "r", encoding="utf-8") as f1, open("%s.bak" % file, "w", encoding="utf-8") as f2:
ss = ''
for line in f1:
# if old_str in line:
# line = line.replace(old_str, new_str)
x = line.split(' ')
ss = str(list.index(x[0]))
for i, val in enumerate(x[1:-1]):
temp = int(val)
# if i == 0 or i == 2:
# temp /= 1920
# else:
# temp /= 1080
ss = ss + ' ' + str(temp)
ss += '\n'
print(ss)
f2.write(ss)
f1.close()
f2.close()
os.remove(file)
os.rename("%s.bak" % file, file)
if __name__ == '__main__':
reset()
思路:先轉成xml格式,再轉成yolo格式
注:圖片名、標簽名不能包含中文
(中文標簽問題有待探索)(20211110)
本周論文速覽
Deep RGB-D Saliency Detection with Depth-Sensitive Attention and Automatic Multi-Modal Fusion
Residual Learning for Salient Object Detection
Progressively Guided Alternate Refinement Network for RGB-D Salient Object Detection
https://www.cnblogs.com/wickyan/p/15525611.html
第十一周
torch.size()用法
>>> import torch
>>> c = torch.arange(60)
>>> d = c.reshape(3, 4, 5)
>>> d.size()
torch.Size([3, 4, 5])
>>> d.size()[1:]
torch.Size([4, 5])
>>> d.size()[2:]
torch.Size([5])
>>> d.size()[3:]
torch.Size([])
torch.chunk()用法
>>> import torch
>>> a=torch.tensor([[[1,2],[3,4]],
[[5,6],[7,8]]])
>>> b=torch.chunk(a,2,dim = 1)
>>> a
tensor([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
>>> b
(tensor([[[1, 2]],
[[5, 6]]]),
tensor([[[3, 4]],
[[7, 8]]]))
第十二周
matplotlib.pyplot
ax.legend()
‘’'loc:圖例位置,可取(‘best’, ‘upper right’, ‘upper left’, ‘lower left’, ‘lower right’, ‘right’, ‘center left’, ‘center , right’, ‘lower center’, ‘upper center’, ‘center’) ;若是使用了bbox_to_anchor,則這項就無效了
fontsize: int或float或{‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’},字體大小;
frameon: 是否顯示圖例邊框,
ncol: 圖例的列的數量,默認為1,
title: 為圖例添加標題
shadow: 是否為圖例邊框添加陰影,
markerfirst: True表示圖例標簽在句柄右側,false反之,
markerscale: 圖例標記為原圖標記中的多少倍大小,
numpoints: 表示圖例中的句柄上的標記點的個數,一般設為1,
fancybox: 是否將圖例框的邊角設為圓形
framealpha: 控制圖例框的透明度
borderpad: 圖例框內邊距
labelspacing: 圖例中條目之間的距離
handlelength: 圖例句柄的長度
bbox_to_anchor: (橫向看右,縱向看下),如果要自定義圖例位置或者將圖例畫在坐標外邊,用它,比如bbox_to_anchor=(1.4,0.8),這個一般配合着ax.get_position(),set_position([box.x0, box.y0, box.width*0.8 , box.height])使用
用不到的參數可以直接去掉,有的參數沒寫進去,用得到的話加進去 , bbox_to_anchor=(1.11,0)
‘’’如果使用ax.legend的話,需在它之前加一句:
ax = plt.gca() #返回坐標軸
才可以用。
語義分割
[1]田萱,王亮,丁琪.基於深度學習的圖像語義分割方法綜述[J].軟件學報,2019,30(02):440-468.
基於像素分類的圖像語義分割方法
ISSbPC方法無需產生目標候選區域, 直接為圖像中的每個像素進行分類, 原始圖像經過一個端到端模型后直接輸出分割結果, 是一種從訓練數據出發, 貫穿整個模型后直接輸出結果的新模式。
CNN與FCN
- 通常cnn網絡在卷積之后會接上若干個全連接層,將卷積層產生的特征圖(feature map)映射成為一個固定長度的特征向量。一般的CNN結構適用於圖像級別的分類和回歸任務,因為它們最后都期望得到輸入圖像的分類的概率,如ALexNet網絡最后輸出一個1000維的向量表示輸入圖像屬於每一類的概率。
- FCN對圖像進行像素級的分類,從而解決了語義級別的圖像分割問題。FCN可以接受任意尺寸的輸入圖像,采用反卷積層對最后一個卷基層的特征圖(feature map)進行上采樣(雙線性插值),使它恢復到輸入圖像相同的尺寸,從而可以對每一個像素都產生一個預測,同時保留了原始輸入圖像中的空間信息,最后奇偶在上采樣的特征圖進行像素的分類。
- 全卷積網絡(FCN)是從抽象的特征中恢復出每個像素所屬的類別。即從圖像級別的分類進一步延伸到像素級別的分類。
FCN的問題
- 圖像經過池化操作后, 特征圖的分辨率不斷降低, 部分像素的空間位置信息丟失;
- 分割過程未能有效地考慮圖像上下文 (image context) 信息, 無法充分利用豐富的空間位置信息, 導致局部特征和全局特征的利用率失衡.
FCCRF
在FCN的末端增加全連接條件隨機場 (fully connected conditional random field, 簡稱FCCRF) , 對粗糙分割圖進行邊界優化, 並使用帶孔卷積 (atrous convolution) 擴大特征圖的感受野 (receptive field, 簡稱RF) , 提出了DeepLab網絡
ASPP帶孔空間金字塔池化
2016提出帶孔空間金字塔池化 (atrous spatial pyramid pooling, 簡稱ASPP) ,利用ASPP整合多尺度特征, 最后, 再用FCCRF優化分割圖像, 在不增加過多參數的情況下, 增大了感受野、提高了分割精度.
膨脹卷積的問題以及解決方法
在ISS過程中, 使用擴張卷積能夠更有效地提取圖像特征、增加感受野, 並保留一部分像素的空間位置信息。
但擴張卷積在操作過程中易產生空間間隙, 會出現信息丟失、信息不相關和局部信息之間的連續性被打斷等問題。
2017年, 文獻[[30](javascript:void(0)😉]使用混合擴張卷積 (hybrid dilated convolution, 簡稱HDC) 代替擴張卷積, 並使用稠密上采樣卷積 (dense upsampling convolution, 簡稱DUC) 替換BI算法.HDC由一系列不同擴張率的擴張卷積模塊組成, 既能增加感受野, 又能保持局部信息的相關性, 有效地避免了上述問題.
第十三周
1 測2020年數據
原論文提供的result就這么幾個,為什么該論文能測出這么多指標?
猜測:該論文使用原論文訓練好的模型(.pth),自行生成result
(如果這樣可以的話,是不是可以把之前缺失的圖片自行補齊?)
2 數據集圖片張數
Datasets | counts | |
---|---|---|
1 | DUT_RGBD | 400 |
2 | LFSD | 100 |
3 | NJUD (NJU2K) | 500 (另見498 485) |
4 | NLPR | 300 |
5 | RGBD135(DES) | 135 |
6 | SIP | 929 |
7 | SSD | 80 |
8 | STERE1000 | 1000 |
9 | STEREO797 | 797 |
3 result缺失情況
LFSD少一張
BTSNet(83)
解決方法:補一張GT
NJUD 498張
CDINet HAINet
解決方法:補兩張GT
NJUD 485張
BTSNet DFMNet UTA
解決方法:不測此數據集
4 PR曲線
4.1 為什么有的曲線兩端很長?這代表了什么?
猜測1:有些result沒有二值化?(經實驗,二值化也沒用)
猜測2:短線說明PR值就集中在短線所在的區間?(廢話)
ToDo: 將坐標軸完整展現(0-1.0),以散點的形式:
4.2 PR曲線的概念
Q: 只有二分類問題,才能畫pr曲線嗎?
4.3 不同epoch之間訓練結果的關系?
猜測:不同epoch之間訓練結果,有水平上的位移關系。
疑問:pr曲線的形狀,在前幾次epoch就已經固定了?
(這不是sod應該考慮的事了,評測指標是多樣化的,哪怕用取巧的方式pr曲線獲勝,又能咋樣)
ToDo:驗證猜想,取不同訓練階段pth進行RGB135測試
做法:取epoch次數:9、19、29、39、49進行預測圖片(紅色線為論文提供的.pth)
結論:雀食有這規律,但是沒啥用。除此之外,結合4.1的散點圖(密集的點,與)
第十四周
三步法快速讀文獻
1.title
2.abstract
3.introduction
4.method
5.experiments
6.conclusion
第一遍:標題、摘要、結論。可以看一看方法和實驗部分重要的圖和表。這樣可以花費十幾分鍾時間了解到論文是否適合你的研究方向。
第二遍:確定論文值得讀之后,可以快速的把整個論文過一遍,不需要知道所有的細節,需要了解重要的圖和表,知道每一個部分在干什么,圈出相關文獻。覺得文章太難,可以讀引用的文獻。
第三遍:提出什么問題,用什么方法來解決這個問題。實驗是怎么做的。合上文章,回憶每一個部分在講什么。
Transformer
- 一個純基於注意力機制的編碼器和解碼器
- 表現比 RNN 架構好,在機器翻譯任務
BERT
- 使用 一個 Transformer 編碼器
- 拓展到更一般的 NLP 的任務
- 使用了 完型填空 的自監督的訓練機制
- 不需要使用標號
- 去預測一個句子里面 不見 masked 的詞
- 從而獲取對文本特征抽取的能力
- BERT 極大的擴展了 Transformer 的應用
- 在一個大規模的、沒有標號的數據上 訓練出非常好的模型出來
ViT
- 將 Transformer 用到 CV 上面
- 把整個圖片分割成很多 16 * 16 的小方塊
- 每一個方塊 patch 做成一個詞 token,然后放進 Transformer 進行訓練
- 證明:訓練數據足夠大 (1,000萬 或者 一個億的訓練樣本)的時候,Transformer 的架構 精度 優於 CNN 架構
MAE:
- BERT 的一個 CV 的版本
- 基於 ViT ,BERT化
- 把整個訓練 拓展到沒有標號的數據上面
- 通過完型填空來獲取圖片的一個理解
- 不是第一個將 BERT 拓展到 CV 上
- MAE 很有可能 未來影響最大
- BERT 加速了 Transformer 架構 在 NLP 的應用
- MAE 加速 Transformer 在 CV 上的應用
- MAE 很有可能 未來影響最大
第十五周
Transformer ( Attention Is All You Need)
僅僅依賴於注意力機制,而完全(entirely)沒用使用循環或者是卷積。
使用了兩個機器翻譯的實驗,顯示此模型效果特別好。
(一開始做的是機器翻譯_相對來說比較小的領域,但是隨着之后bert、gbt把這個架構運用在更多的自然語言處理的、任務上,工作才出圈了。以至於之后運用在cv上 )
想法:能不能1使用深度圖,2使用RGB圖,進行“自注意力”(他注意力)。當然這會造成RGB的語義丟失,所以做這操作之前,再用一個transformer塊,真正的transformer塊,1、2都是RGB圖。
也就是說,第二個“他注意力塊”僅僅起到深度信息提取融合的作用。(想法很天真,有待驗證)還要處理peoitional encoding的內內容,時序信息以及位置信息(cv真的需要時許信息嗎?)
RNN的梯度消失和普通網絡不太一樣,它的梯度被近距離梯度主導,被遠距離梯度忽略
朝花夕拾
注意力機制
通道注意力
SENet(Squeeze-and-Excitation Networks)
https://www.bilibili.com/video/BV1SA41147uA
三個操作:
- 全局池化壓縮(Global pooling-Squeeze),將每個通道的二位特征(H*W)壓縮成一個實數(論文通過平均池化實現)
空間注意力
深度預測
https://www.cnblogs.com/ivan-chen/p/10446946.html
雙目深度預測
單目深度預測
https://www.cnblogs.com/jukan/p/10151898.html
第一類 僅僅依靠深度學習和網絡架構得到結果
第二類 依靠於深度信息本身的性質
第三類 基於CRF的方法
第四類 基於相對深度
第五類 非監督學習
https://www.sohu.com/a/424043597_100007727
視頻深度預測
奇思妙想:前幀與后幀之間,相當於無數多目攝像頭(攝像頭移動的場景) (復眼?),但是前一幀與后一幀之間的位移如何計算?
奇思妙想已經被實現了:[SIGGRAPH 2020] Consistent Video Depth Estimation:https://github.com/facebookresearch/consistent_depth
第十六周
IEEE TPAMI 2021: MobileSal: Extremely Efficient RGB-D Salient Object Detection
存在問題
移動網絡在特征表示方面不如笨重的網絡強大,如果適當利用彩色圖像的深度信息,可以增強與SOD相關的特征表示。
主要貢獻
-
提出了一種隱式深度恢復(IDR)技術來增強移動網絡對RGB-D SOD的特征表示能力。(IDR僅在訓練階段采用,在測試過程中省略,因此預測成本很低。)
僅在最粗略的級別上進行RGB和深度信息融合,因為這樣小的特征分辨率(即1/32比例)對於降低計算成本至關重要。
-
提出了緊湊金字塔細化(CPR)方法,用於有效的多級特征聚合,以獲得邊界清晰的顯著對象。
實現方法
骨干
MobileNetV2主干中刪除了全局平均池層和最后一個完全連接的層。
對於RGB流,每個階段后面都有一個步長為2的卷積層,因此,在每個階段之后,特征貼圖將被降采樣為半分辨率。
對於Depth流,由於深度貼圖包含的語義信息少於相應的RGB圖像,因此我們構建了一個輕量級深度網絡,其卷積塊數少於RGB流。每個階段只有兩個反向剩余塊(IRB)
思考
MobileNet
參數個數比較
AlexNet 六千萬
GooleNet 七百萬
VGG 一億三千八百萬
Xceotion 二千萬
MobileNet V1 四百萬
MobileNet V2 三百萬
傳統卷積:
https://thomelane.github.io/convolutions/2DConvRGB.html
一個卷積核能同時處理多個通道的信息,原圖輸入是三通道,卷積核也就是三通道,一個卷積核生成一個faturemap。
Depthwise separable convolution
深度可分離卷積:
Depthwise:每個輸入通道使用單獨的二維卷積,每個卷積核只處理單通道的信息。
Pointwise:捕捉跨通道信息,使用1x1卷積,處理所有通道信息
優點
傳統參數量:輸入(長x寬x深度)Df x 卷積核(長x寬)Dk x 輸出(深度)
深度分離卷積:輸入(長x寬x深度) x 卷積核(長x寬) + 輸入(深度) x 輸出(深度) x 卷積核(長x寬)
局限
- 沒有殘差連接
- 很多Depthwise卷積訓練出來是0
- 卷積核、權重數量和通道數量太少、太單薄
- ReLU
- 低精度
MobileNetV2
Inverted residual block
傳統殘差模塊:先1x1卷積降維,在低維空間下再用3x3標准卷積,再1x1卷積升維。殘差捷徑,連接通道較多的tensor
Inverted residual block:先用1x1卷積升維,在高維空間下用DepthWise卷積,再用1x1卷積降維,降維的時候使用線性激活函數ReLU6。殘差連接通道數比較少的tensor
這樣做的好處
在低維條件下ReLU會造成信息丟失
具體實現
總結
Depthwise + Pointwise 能有效減少參數
Inverted residual block 能有效提高性能(炸到高維所造成的參數變大如何解決?)
所以說,總體性能有所提高,總體參數量呢?
朝花夕拾
1 * 1 卷積作用
實現降維、升維操作
im2col 運算
作用:加速卷積運算
將每個卷積核變成行向量,每個感受野變成列向量,讓每個行向量乘以列向量,得到的結果就是卷積運算得到的結果。https://www.bilibili.com/video/BV16b4y117XH (54:09)
VSCode
傳說中的最受歡迎的IDE
使用PyCharm遠程開發每次需要上傳很不爽,所以,決定換VSCode(大概是個錯誤的決定)
VS Code遠程開發教程
https://mp.weixin.qq.com/s/ZDVYk188oPLugRI6oeVYIQ
Win的Openssh
https://docs.microsoft.com/zh-cn/windows-server/administration/openssh/openssh_install_firstuse
可以遠程anaconda,VS Code遠程開發,和linux如出一轍(PyCharm不支持windows)
PS:公鑰驗證總是無法通過,遂使用密碼登錄
VSCode 自動定位根目錄
而不是當前文件目錄
打開菜單:文件 --> 首選項 --> 設置,打開設置界面后,在搜索框輸入:execute
http://www.wb86.com/post/353.html
VSCode 無法import自己寫的包
解決方法:
import sys, os
sys.path.append(os.pardir)
第十八周
重啟Ubuntu圖形化界面
sudo pkill Xorg
crontab查看任務列表
crontab -e
crontab定時任務
crontab */1 * * * * /home/unname/anaconda3/bin/python YWQ/autoget.py # 每分鍾執行,PS要寫python的絕對路徑
crontab查看日志
vim /var/log/syslog
校園網自動登錄
import requests
import json
import time
_USERNAME_ = ""
_PASSWORD_ = ""
def network_down() :
url = "http://172.16.8.70/drcom/chkstatus"
headers = {
'callback': "dr1002",
'jsVersion': "4.1",
'v': "7808",
'lang': "zh",
}
res = requests.get(url, params=headers)
ss = res.text[12:-4]
return 1 != json.loads(ss)['result']
def network_login():
print(network_down())
if network_down():
url = "http://172.16.8.70/drcom/login"
headers = {
'callback': "dr1003",
'DDDDD': _USERNAME_,
'upass': _PASSWORD_,
'0MKKey': "123456",
'R1': "0",
'R2': "",
'R3': "0",
'R6': "0",
'para': "00",
'v6ip': "",
'terminal_type': "1",
'lang': "zh-cn",
'jsVersion': "4.1.3",
'v': "7381",
'lang': "zh",
}
res = requests.get(url, params=headers)
ss = res.text[12:-4]
print(ss)
j = json.loads(ss)
if 1 == j['result']:
print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) + '---認證成功,ip為:' + j['v46ip'])
network_login()
ToDo:用域名做DDNS
https://www.freenom.com/ 免費域名網站
選擇域名的時候要加上后綴,否則會顯示"不可用"。
第十九周
朝花夕拾
評價指標
為什么用GAP替換全連接層
在卷積神經網絡的初期,卷積層通過池化層(一般是 最大池化)后總是要一個或n個全連接層,最后在softmax分類。其特征就是全連接層的參數超多,使模型本身變得非常臃腫。
之后,有大牛在NIN(Network in Network)論文中提到了使用全局平局池化層代替全連接層。
global average pooling 與 average pooling 的差別就在 “global” 這一個字眼上。global與 local 在字面上都是用來形容 pooling 窗口區域的。 local 是取 feature map 的一個子區域求平均值,然后滑動這個子區域; global 顯然就是對整個 feature map 求平均值了。
因此,global average pooling 的最后輸出結果仍然是 10 個 feature map,而不是一個,只不過每個feature map 只剩下一個像素罷了。這個像素就是求得的平均值。 官方 prototxt 文件 里寫了。網絡進行到最后一個average pooling 層的時候,feature map 就剩下了 10 個,每個大小是 8 * 8。順其自然地作者就把pooling 窗口設成了 8 個像素,意會為 global average pooling 。可見,global averagepooling 就是窗口放大到整個 feature map 的 average pooling 。
第二十周
語義分割
了解語義分割,僅作為拓寬視野,尋找靈感之用。論文未必精讀,原理未必深究。
3d語義分割大多使用點雲等特征,暫時沒有深入了解點雲的想法。
ABMDRNet: Adaptive-weighted Bi-directional Modality Difference Reduction Network for RGB-T Semantic Segmentation
↑ RGB-T分割論文(CVPR2021僅此一篇,后續大概會詳細解讀)
我們討論的語義分割,都將以2D為基准,關注點放在encoder和decoder的特征提取和特征融合之上,不詳細討論分類問題。
最常見(並不是最簡單)的分割網絡U-net,其左邊為encoder,右邊為decoder。其中灰色連接線(copy & crop)相當於側輸出,如下圖。
主流圖像分割往往基於FCN(Fully Convolutional Network),顧名思義,去除了全連接層,最后通過上采樣,得到n層輸出,每層都代表分割出來的一個類別。
此處僅從三篇論文,每個方向各找一個解決方式:
分辨率低
很容易想到的解決方式
-
融合別的特征
- 加入殘差網絡(前一層的信息加到后一層)
- 加入側輸出的連結(encoder側輸出與decoder進行融合)
-
上采樣恢復像素
HRNet
Deep High-Resolution Representation Learning for Human Pose Estimation(CVPR2019)
https://arxiv.org/abs/1902.09212
https://github.com/leoxiaobin/deep-high-resolution-net.pytorch這個論文有更新的輕量級版本Lite-HRNet: A Lightweight High-Resolution Network(CVPR2021)
HRNet通過並行連接高分辨率到低分辨率卷積來保持高分辨率表示,並通過重復跨並行卷積執行多尺度融合來增強高分辨率表示。
以前的方法:通過引入上采樣操作和/或組合空洞卷積減少降采樣次數來提升表征的分辨率,典型的結構包括Hourglass、U-Net等。
作者認為:
- 低分辨率表征通過上采樣得到的高分辨率表征,其本身雖然擁有很好的語義表達能力,但是上采樣本身並不能完整地彌補空間分辨率的損失。
- 原本的高分辨率表征,但是由於只經過了少量的卷積操作,其本身只能提供低層次的語義表達;
應該為高分辨率表征學習建立新的網絡結構
HRNet不同於別的卷積串聯,它是並行連接。
多次對高低分辨率特征進行信息補足,在實驗中取得了很好的效果。
上下文信息缺失
OCRNet
Segmentation Transformer: Object-Contextual Representations for Semantic Segmentation(ECCV2020)
https://arxiv.org/abs/1909.11065
https://github.com/HRNet/HRNet-Semantic-Segmentation/tree/HRNet-OCR
語義分割任務的兩大關鍵是:分辨率和上下文
- 密集像素預測任務,空間分辨率很重要。
- 像素本身不具備語義,它的語義尤其圖像整體或目標區域決定,因此它對上下文高度依賴。
主要思路是利用目標區域表示來增強其像素的表示。
與別的論文考慮上下文關系的方法不同的是,之前的方法考慮的是上下文像素之間的關系,沒有顯示利用目標區域的特征。
上下文的空間范圍:ASPP, PPM
上下文像素關系:DANet, CFNet, OCNet
文章3.2 3.3有詳細闡述(未完待續)
第二十一周
語義分割
書接前文
上下文信息缺失
上下文信息缺失,我們往往會想到兩種解決方式
- 全局平均池化
- 金字塔孔卷積
OCRNet
OCR 方法的實現主要包括3個階段:
- 根據網絡中間層的特征表示估測一個粗略的語義分割結果作為 OCR 方法的一個輸入 ,即軟物體區域(Soft Object Regions)
- 根據粗略的語義分割結果和網絡最深層的特征表示計算出 K 組向量,即物體區域表示(Object Region Representations),其中每一個向量對應一個語義類別的特征表示
- 計算網絡最深層輸出的像素特征表示(Pixel Representations)與計算得到的物體區域特征表示(Object Region Representation)之間的關系矩陣,然后根據每個像素和物體區域特征表示在關系矩陣中的數值把物體區域特征加權求和,得到最后的物體上下文特征表示 OCR (Object Contextual Representation) 。當把物體上下文特征表示 OCR 與網絡最深層輸入的特征表示拼接之后作為上下文信息增強的特征表示(Augmented Representation),可以基於增強后的特征表示預測每個像素的語義類別。
邊界錯誤
邊界錯誤,我們往往會想到兩種解決方式
- 提取邊界信息,在輸出前融合,來提升分割效果
- 引入邊緣檢測任務,以多任務學習的形式來強化邊緣的預測
SegFix
SegFix: Model-Agnostic Boundary Refinement for Segmentation (ECCV2020)
https://arxiv.org/pdf/2007.04269v1.pdf
https://github.com/openseg-group/openseg.pytorch
預測誤差的主要來源就是邊界附近的區域,而區域內部的預測一般都很准確,因此直接使用某一類別內部像素作為邊界預測。
作者通過將邊界像素的標簽替換為可靠的內部像素的標簽,來基於偏移圖,優化粗略的標簽圖。 作者用不同的箭頭表示不同的偏移矢量。 紅框標記粗標簽圖中的錯誤位置,綠框標記矯正后的位置。
本文提出了一種后處理算法,主要包含兩塊內容
- 通過數據事先訓練得到的用來生成邊緣區域坐標偏移圖的結構
- 通過使用偏移圖來優化現有模型在邊緣區域上的預測的結構
- 首先將輸入圖像發送到主干中,以預測特征圖。
- 然后,用邊界預測分支(boundary branch)來預測二元邊界映射圖(binary boundary map),用方向預測分支(邊界分支)來預測方向映射圖(direction map),並用二元邊界映射來覆蓋它。
- 分別在預測的邊界圖和方向圖上應用邊界損失和方向損失。
- 在testing階段,首先將方向圖轉換為偏移圖(direction map to offset map),然后根據偏移圖對現有方法的分割結果進行細化。
邊界分支
- 1×1 Conv -> BN -> ReLU with 256 output channels -> a linear classifier (1x1 Conv) -> Up-sample the prediction to generate the final boundary map $ B ∈ R ^{H × W × 1 }$ which records the probability of the pixel belonging to the boundary
- 訓練時由真值boundary map監督約束,使用二值交叉熵損失作為邊界損失,學習良好的邊緣檢測
- 測試時直接生成邊緣圖
方向預測分支
-
1 × 1 Conv -> BN -> ReLU with 256 output channels -> a linear classifier (1×1 Conv) -> Up-sample the classifier prediction to generate the final direction map \(D ∈ R ^{H × W × m}\) . We mask the direction map \(D\) by multiplying by the (binarized) boundary map \(B\) to ensure that we only apply direction loss on the pixels identified as boundary by the boundary branch.
-
預測所有位置的像素與之最近的同類像素的方向,這里的方向不是連續的,而是對\([0,2\pi)\) 量化成m個值后的結果(In fact, we empirically find that our discrete categorization scheme outperforms the regression scheme, e.g., mean squared loss in the angular domain [Deep watershed transform for instance segmentation], measured by the final segmentation performance improvements)
-
訓練時使用真值direction map監督該分支生成的離散方向,使用多分類交叉熵損失(standard category-wise cross-entropy loss)來作為方向預測損失
-
測試時同樣直接生成離散方向圖
獲取真值
b使用了9x9的Sobel濾波器。(簡直頭大)(后面一部分沒看懂,知道大概思想,實現真的看不懂了)
手機攝像頭發展簡史
多目攝像頭
HTC EVO 3D(2011) 雙目攝像頭,產生左右眼畫面,通過光柵技術,使左右眼觀感不同,產生3D效果。
HTC One M8(2014)真正的雙攝鼻祖,加入了景深攝像頭,實現了先拍照,再模態融合,摳圖,對焦(背景虛化)(RGB-D攝像頭)。
榮耀6plus(2014),兩顆參數完全一樣的攝像頭,同時參與實際成像過程,但是成像很慢。兩個800萬攝像頭合成1300萬像素照片,增大感光元件大小。
華為p9、p10 & 小米6(2016),RGB + 黑白攝像頭。彩色攝像頭記錄拍攝時的色彩;黑白單色傳感器對定點的射入光線進行測量,只負責捕捉細節(進光量大很多)。(當前2019年華為P30的攝像頭RYYB傳感器也是通過類似的方式,增加進光量)
單目攝像頭
蘋果的iPhone和谷歌的pixel,至始至終采用的都是單目攝像頭方案。
現在所有主流的手機(2021年)采用的都是單目方案,每個攝像頭只負責一個焦段,成像的時候,只有一個攝像頭在工作。
反思
Q1:為什么手機廠商紛紛放棄了多模態攝像頭?
A1:近年來,相機傳感器越來越大,外加多幀融合(HDR)算法,已經能彌補進光量不足的問題。景深虛化問題,谷歌用兩種方式解決:
- 把每個像素拆成兩半,人為分割成兩個不同位置的畫面,相位對焦技術(PDAF),用此項技術,谷歌分割人像主體和背景(做兩次成像,一次左半像素,一次右半像素,模擬雙目攝像頭)。
- 谷歌把五個攝像頭綁在一起,采集大量照片,訓練出一套景深模型,實際拍照的時候只需要提供一張攝像頭的成像,也能依據現有的模型分離出背景和主體。(PS:人眼識別距離的方式,不僅利用雙眼的相位差,還根據陰影、紋理、遮擋等信息以及自己的先驗知識去判斷物體的位置)
Q2:為什么在論文中多模態融合是主流趨勢?
A2:在圖像質量、數量不變的情況下,尋求更多模態的信息,是很有效的。而工程領域與科研領域不同,工程問題遇到像素不夠,深度圖不夠清晰的情況下,首先想到的是:提高像素能不能解決?增加訓練數據集,能不能解決?如果能,問題解決。
特斯拉如今(2021)采用純視覺方案,與谷歌、蘋果手機堅持使用單攝像頭有很大的相似之處。車機性能更好了,能處理多路4k60幀RGB信息流,再加上深度學習算法的迭代,以至於不再需要更多傳感器提供信息。不知道三五年之內,特斯拉的解決方案是會應用更廣泛,還是會被淘汰掉。
第二十二周
Salient object detection network with multi-scale feature refinement and boundary feedback
Image and Vision Computing(中科院三區)
當前存在問題
-
上采樣和池化操作可能會導致邊界模糊(全連接的CRF方法作為后處理階段來保留邊界,耗時很大)。
-
具有不同特征的多層次特征存在融合問題(現存的主流方法通常通過直接級聯或求和運算來融合多尺度特征,忽略了不同尺度之間的相互作用)。
解決方案
- 提出一種特征交互方案用於描述
- 不同尺度的特征
- 層內的信息交互
- 提出一種特征細化模塊 -> 自適應選擇有用的側輸出 -> 生成粗特征圖
- 利用提取出的特征信息,以粗 -> 精的方式生成顯著圖
(未完待續。。。)
conda initialize
如果在安裝anaconda的時候選擇了初始化,則每次打開命令行,默認進入(base)環境,只需要將~/.bashrc中以下初始化內容刪除即可(別忘了source ~/.bashrc更新環境變量)
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/home/wickyan/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
eval "$__conda_setup"
else
if [ -f "/home/wickyan/anaconda3/etc/profile.d/conda.sh" ]; then
. "/home/wickyan/anaconda3/etc/profile.d/conda.sh"
else
export PATH="/home/wickyan/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<<
conda:未找到命令的解決方法
在使用anaconda裝python時,有時候路徑可能沒有加入到系統路徑中,要手動加入:
將anaconda的bin目錄加入PATH,根據版本不同。確定anaconda的名字,如果是默認的,python3.7生成anaconda3
$ echo 'export PATH="~/anaconda3/bin:$PATH"'>>~/.bashrc
然后更新bashrc,即可立即生效,不用關機,source ~/.bashrc用來重啟環境變量。
$ source ~/.bashrc
第二塊磁盤掛載到/home下
注意/dev/sdb1還是/dev/sdb,不要寫錯。
否則重啟不能進系統(可用光盤鏡像進入修復)
教程:https://blog.csdn.net/u011932817/article/details/102878605
官方教程:https://help.ubuntu.com/community/Partitioning/Home/Moving
硬盤掛載流程
#硬盤掛載流程
#尋找到自己的硬盤
sudo fdisk -l
#掛載到/media/temp(x)/下
sudo mount /dev/sdb1 /media/temp/
#卸載硬盤
sudo umount /media/temp/
顯卡查看
watch -n 1 nvidia-smi # 每秒查看一次顯卡
torch.cuda.is_available() # 查看顯卡是否可用
torch.cuda.device_count() # 查看顯卡數量
torch.cuda.set_device(0) # 指定運行在第0張顯卡上(官方不推薦使用)
torch.cuda.current_device() # 查看當前使用顯卡
多顯卡選擇
CUDA_VISIBLE_DEVICES=1 python3 tools/train.py # shell運行時使用
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "1" # 和第一種一樣
torch.cuda.set_device(0) # 不推薦使用