一. pytorch多卡訓練的原理
原理:
(1)將模型加載到一個指定的主GPU上,然后將模型淺拷貝到其它的從GPU上;
(2)將總的batch數據等分到不同的GPU上(坑:需要先將數據加載到主GPU上);
(3)每個GPU根據自己分配到的數據進行forward計算得到loss,并通過backward得到權重梯度;
(4)主GPU將所有從GPU得到的梯度進行合并并用于更新模型的參數。
實現:
(1)模型方面
device_ids = [0, 1, 2, 3]
model = Model(input_size, output_size)
model = nn.DataParallel(model, device_ids=device_ids) #單卡沒有這行代碼
model = model.cuda(device_ids[1]) #指定哪塊卡為主GPU,默認是0卡
(2)數據方面
for data in data_loader:
input_var = Variable(data.cuda(device_ids[1])) #默認指定用0卡先加載數據就會報錯
output = model(input_var)
二. pytorch中gather和scatter_
- gather(聚合操作)
(1)函數原型:torch.gather(input, dim, index, out=None);
(2)函數功能:對于out指定位置上的值,去尋找input里面對應的索引位置,根據是index;
(3)三維數組的通項公式
out[i][j][k] = input[index[i][j][k]][j][k] # if dim = 0
out[i][j][k] = input[i][index[i][j][k]][k] # if dim = 1
out[i][j][k] = input[i][j][index[i][j][k]] # if dim = 2
- scatter_(分散操作)
(1)函數原型:Tensor.scatter_(dim, index, src)
(2)函數功能:src(或者說input)指定位置上的值,去分配給output對應索引位置,根據是index;
(3)三維數組的通項公式:
self[index[i][j][k]][j][k] = src[i][j][k] # if dim == 0
self[i][index[i][j][k]][k] = src[i][j][k] # if dim == 1
self[i][j][index[i][j][k]] = src[i][j][k] # if dim == 2
三. pytorch中torch.Tensor()和torch.tensor()的相同點和區別
- 相同點
Tensor和tensor都能用于生成新的張量
>>> a=torch.Tensor([1,2])
>>> a
tensor([1., 2.])
>>> a=torch.tensor([1,2])
>>> a
tensor([1, 2])
- 不同點
torch.Tensor()是python類,是torch.FloatTensor()的別名,使用torch.Tensor()會調用Tensor類的構造函數,生成float類型的張量;
而torch.tensor()僅僅是python的函數,函數原型是torch.tensor(data, dtype=None, device=None, requires_grad=False),其中data可以是scalar,list,tuple,numpy array等等。
然后torch.tensor會從data中的數據部分進行拷貝(而不是引用),根據原始數據類型生成相應的 torch.LongTensor、torch.FloatTensor和torch.DoubleTensor。比如:
>>> a=torch.tensor([1,2])
>>> a.type()
'torch.LongTensor'
>>> a=torch.tensor([1.,2.])
>>> a.type()
'torch.FloatTensor'
>>> a=np.zeros(2,dtype=np.float64)
>>> a=torch.tensor(a)
>>> a.type()
'torch.DoubleTensor'
四. pytorch中Variable的理解
torch.autograd.Variable是Autograd的核心類,它封裝了Tensor,并整合了反向傳播的相關實現。Variable包含了三個屬性:
(1)data:存儲了Tensor本體的數據;
(2)grad:保存了data的梯度,其本身也是個Variable,shape與data相同;
(3)grad_fn:指向Function對象,用于反向傳播的梯度計算。但是在pytorch0.4之后,將Variable與Tensor整合到了一起,聲明torch.tensor也包含這三個屬性。
五. pytorch中backward()的理解
https://blog.csdn.net/sinat_28731575/article/details/90342082
六. tensorflow中variable和get_variable的區別
(1)variable是用來創建變量的,當兩個變量的名字在同一作用域內相同時,tensorflow會自動將第二個定義的variable的名字加上"_1",則會生成新的name,如果使用在name_scope內,則會在name的前面加上name_scope名字的前綴;
(2)get_variable的功能是用來進行變量共享的,當變量不存在時,則會自動創建該變量。如果存在時,需要設置reuse=True來獲取該變量,實現變量共享。需要注意的是,get_variable在variable_scope內使用才會給name加上前綴,在name_scope中使用并不會。
七. tensorflow中節點和邊代表的什么
(1)節點代表著多種功能,比如說輸入,變量初始化,運算,控制,輸出等;
(2)邊代表輸入與輸出之間的關系,即數據流動的方向。
八. pytorch中train和eval有什么不同
(1). model.train()——訓練時候啟用
啟用 BatchNormalization 和 Dropout,將BatchNormalization和Dropout置為True
(2). model.eval()——驗證和測試時候啟用
不啟用 BatchNormalization 和 Dropout,將BatchNormalization和Dropout置為False
train模式會計算梯度,eval模式不會計算梯度。
九、caffe的im2col
參考 caffe在實現卷積的時候,將kernel展開成行向量(每一行表示一個輸出channel,output channel為幾,就有幾個行向量),將input tensor展開成列向量(im2col操作),但是是根據kernel的shape展開,(kernel能滑動多少次,就有多少列),不同的input channel被分成了很多矩陣塊,但是都是“縱向放置”,然后將kernel和input tensor做矩陣乘法,得到output_channels行,output_h * output_w列的矩陣,每一行都可以展開成一張輸出特征圖(由于圖像數據是連續存儲的,只需要按行按列排滿即可)。
PS:不同框架的訪存機制不一樣,所以會有行列相反這樣的區別。python和c++的數據存儲是行優先,matlab是列優先。所以,在caffe框架下,im2col是將一個小窗的值展開為一行,而在matlab中則展開為列。所以說,行列的問題沒有本質區別,目的都是為了在計算時讀取連續的內存。
十. tensorflow底層實現卷積的方式
參考 pytorch,tensorflow,caffe底層實現卷積的核心都是im2col, 這里以tensorflow為例。
tf.nn.conv2d()函數的定義為:
conv2d(input,filter,strides,padding,use_cudnn_on_gpu=True,data_format="NHWC",dilations=[1,1,1,1],name=None)
給定 4-D input 和 filter tensors計算2-D卷積,其中input tensor 的 shape是: [B, H, W, C],filter / kernel tensor 的 shape是: [filter_height, filter_width, in_channels, out_channels]
卷積op執行方式:
- 將filter展開為一個 shape 為[filter_height * filter_width * in_channels, out_channels] 大小的2-D 矩陣。
- 從 input tensor按照每個filter位置上提取圖像patches來構成一個虛擬的shape大小為[batch, out_height, out_width,filter_height * filter_width * in_channels]的tensor 。(相當于在input每個卷積核的位置上(包含了同一位值對應的不同channel)提取patches)
ps:把輸入圖像要經行卷積操作的這一區域展成列向量的操作通常稱為im2col - 對每個patch, 右乘以 filter matrix.得到[batch, out_height, out_width,out_channels]大小的輸出。(Input maps的第一列×kernels的第一行,得到輸出的第一個值,Input maps的第i列×kernels的第j行,得到輸出特征圖第i列第 j行的值)
十一. Pytorch和tensorflow區別,底層分別是怎么實現動態圖和靜態圖的?
tensorflow實現反向傳播:
import tensorflow as tf
weight = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
biases = tf.Variable(tf.zeros([1]))
y = weight * x_data + biases
loss = tf.reduce_mean(tf.square(y - y_data)) # 計算loss
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.05)
train_step = optimizer.minimize(loss)
init = tf.initialize_all_variables()
sess.run(init)
sess.run(train_step, feed_dict={x_data:x, y_data:y})
pytorch實現反向傳播:loss.backward()