一. pytorch多卡訓(xùn)練的原理
原理:
(1)將模型加載到一個指定的主GPU上购啄,然后將模型淺拷貝到其它的從GPU上;
(2)將總的batch數(shù)據(jù)等分到不同的GPU上(坑:需要先將數(shù)據(jù)加載到主GPU上)扣泊;
(3)每個GPU根據(jù)自己分配到的數(shù)據(jù)進(jìn)行forward計(jì)算得到loss,并通過backward得到權(quán)重梯度;
(4)主GPU將所有從GPU得到的梯度進(jìn)行合并并用于更新模型的參數(shù)所刀。
實(shí)現(xiàn):
(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嫡霞,默認(rèn)是0卡
(2)數(shù)據(jù)方面
for data in data_loader:
input_var = Variable(data.cuda(device_ids[1])) #默認(rèn)指定用0卡先加載數(shù)據(jù)就會報(bào)錯
output = model(input_var)
二. pytorch中g(shù)ather和scatter_
- gather(聚合操作)
(1)函數(shù)原型:torch.gather(input, dim, index, out=None)瓶埋;
(2)函數(shù)功能:對于out指定位置上的值,去尋找input里面對應(yīng)的索引位置诊沪,根據(jù)是index养筒;
(3)三維數(shù)組的通項(xiàng)公式
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)函數(shù)原型:Tensor.scatter_(dim, index, src)
(2)函數(shù)功能:src(或者說input)指定位置上的值,去分配給output對應(yīng)索引位置端姚,根據(jù)是index晕粪;
(3)三維數(shù)組的通項(xiàng)公式:
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()的相同點(diǎn)和區(qū)別
- 相同點(diǎn)
Tensor和tensor都能用于生成新的張量
>>> a=torch.Tensor([1,2])
>>> a
tensor([1., 2.])
>>> a=torch.tensor([1,2])
>>> a
tensor([1, 2])
- 不同點(diǎn)
torch.Tensor()是python類,是torch.FloatTensor()的別名渐裸,使用torch.Tensor()會調(diào)用Tensor類的構(gòu)造函數(shù)巫湘,生成float類型的張量;
而torch.tensor()僅僅是python的函數(shù)橄仆,函數(shù)原型是torch.tensor(data, dtype=None, device=None, requires_grad=False)剩膘,其中data可以是scalar,list盆顾,tuple怠褐,numpy array等等。
然后torch.tensor會從data中的數(shù)據(jù)部分進(jìn)行拷貝(而不是引用)您宪,根據(jù)原始數(shù)據(jù)類型生成相應(yīng)的 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磷杏,并整合了反向傳播的相關(guān)實(shí)現(xiàn)溜畅。Variable包含了三個屬性:
(1)data:存儲了Tensor本體的數(shù)據(jù);
(2)grad:保存了data的梯度极祸,其本身也是個Variable慈格,shape與data相同;
(3)grad_fn:指向Function對象遥金,用于反向傳播的梯度計(jì)算浴捆。但是在pytorch0.4之后,將Variable與Tensor整合到了一起稿械,聲明torch.tensor也包含這三個屬性选泻。
五. pytorch中backward()的理解
https://blog.csdn.net/sinat_28731575/article/details/90342082
六. tensorflow中variable和get_variable的區(qū)別
(1)variable是用來創(chuàng)建變量的,當(dāng)兩個變量的名字在同一作用域內(nèi)相同時美莫,tensorflow會自動將第二個定義的variable的名字加上"_1"页眯,則會生成新的name,如果使用在name_scope內(nèi)厢呵,則會在name的前面加上name_scope名字的前綴窝撵;
(2)get_variable的功能是用來進(jìn)行變量共享的,當(dāng)變量不存在時述吸,則會自動創(chuàng)建該變量忿族。如果存在時,需要設(shè)置reuse=True來獲取該變量蝌矛,實(shí)現(xiàn)變量共享道批。需要注意的是,get_variable在variable_scope內(nèi)使用才會給name加上前綴入撒,在name_scope中使用并不會隆豹。
七. tensorflow中節(jié)點(diǎn)和邊代表的什么
(1)節(jié)點(diǎn)代表著多種功能,比如說輸入茅逮,變量初始化璃赡,運(yùn)算,控制献雅,輸出等碉考;
(2)邊代表輸入與輸出之間的關(guān)系,即數(shù)據(jù)流動的方向挺身。
八. pytorch中train和eval有什么不同
(1). model.train()——訓(xùn)練時候啟用
啟用 BatchNormalization 和 Dropout侯谁,將BatchNormalization和Dropout置為True
(2). model.eval()——驗(yàn)證和測試時候啟用
不啟用 BatchNormalization 和 Dropout,將BatchNormalization和Dropout置為False
train模式會計(jì)算梯度,eval模式不會計(jì)算梯度墙贱。
九热芹、caffe的im2col
參考 caffe在實(shí)現(xiàn)卷積的時候,將kernel展開成行向量(每一行表示一個輸出channel惨撇,output channel為幾伊脓,就有幾個行向量),將input tensor展開成列向量(im2col操作)魁衙,但是是根據(jù)kernel的shape展開报腔,(kernel能滑動多少次,就有多少列)剖淀,不同的input channel被分成了很多矩陣塊榄笙,但是都是“縱向放置”,然后將kernel和input tensor做矩陣乘法祷蝌,得到output_channels行,output_h * output_w列的矩陣帆卓,每一行都可以展開成一張輸出特征圖(由于圖像數(shù)據(jù)是連續(xù)存儲的巨朦,只需要按行按列排滿即可)。
PS:不同框架的訪存機(jī)制不一樣剑令,所以會有行列相反這樣的區(qū)別糊啡。python和c++的數(shù)據(jù)存儲是行優(yōu)先,matlab是列優(yōu)先吁津。所以棚蓄,在caffe框架下,im2col是將一個小窗的值展開為一行碍脏,而在matlab中則展開為列梭依。所以說,行列的問題沒有本質(zhì)區(qū)別典尾,目的都是為了在計(jì)算時讀取連續(xù)的內(nèi)存役拴。
十. tensorflow底層實(shí)現(xiàn)卷積的方式
參考 pytorch,tensorflow钾埂,caffe底層實(shí)現(xiàn)卷積的核心都是im2col河闰, 這里以tensorflow為例。
tf.nn.conv2d()函數(shù)的定義為:
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計(jì)算2-D卷積褥紫,其中input tensor 的 shape是: [B, H, W, C]姜性,filter / kernel tensor 的 shape是: [filter_height, filter_width, in_channels, out_channels]
卷積op執(zhí)行方式:
- 將filter展開為一個 shape 為[filter_height * filter_width * in_channels, out_channels] 大小的2-D 矩陣。
- 從 input tensor按照每個filter位置上提取圖像patches來構(gòu)成一個虛擬的shape大小為[batch, out_height, out_width,filter_height * filter_width * in_channels]的tensor 髓考。(相當(dāng)于在input每個卷積核的位置上(包含了同一位值對應(yīng)的不同channel)提取patches)
ps:把輸入圖像要經(jīng)行卷積操作的這一區(qū)域展成列向量的操作通常稱為im2col - 對每個patch, 右乘以 filter matrix.得到[batch, out_height, out_width,out_channels]大小的輸出部念。(Input maps的第一列×kernels的第一行,得到輸出的第一個值,Input maps的第i列×kernels的第j行印机,得到輸出特征圖第i列第 j行的值)
十一. Pytorch和tensorflow區(qū)別矢腻,底層分別是怎么實(shí)現(xiàn)動態(tài)圖和靜態(tài)圖的?
tensorflow實(shí)現(xiàn)反向傳播:
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)) # 計(jì)算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實(shí)現(xiàn)反向傳播:loss.backward()