レスネット
ResNet は残差ネットワークとも呼ばれ、最適化が容易で、かなりの深さを追加することで精度を向上させることができます。その内部残差ブロックはスキップ接続を使用しており、これにより、深いネットワークの深さの増加によって引き起こされる勾配消失の問題が軽減されます。以下は残差関数と残差学習です。
レスネクスト
ResNeXt は、ResNet と Inception を組み合わせたものです。ResNext は、グループの数 (カーディナリティ) を制御して 2 つの戦略間のバランスを達成することにより、通常の畳み込みとカーネル深度分離可能な畳み込みの間の戦略、つまりグループ畳み込みを提案します。
犬猫戦争の練習
最初に VGG モデルを作成します
model_vgg = models.vgg16(pretrained=True)
with open('./imagenet_class_index.json') as f:
class_dict = json.load(f)
dic_imagenet = [class_dict[str(i)][1] for i in range(len(class_dict))]
inputs_try , labels_try = inputs_try.to(device), labels_try.to(device)
model_vgg = model_vgg.to(device)
outputs_try = model_vgg(inputs_try)
print(outputs_try)
print(outputs_try.shape)
'''
可以看到结果为5行,1000列的数据,每一列代表对每一种目标识别的结果。
但是我也可以观察到,结果非常奇葩,有负数,有正数,
为了将VGG网络输出的结果转化为对每一类的预测概率,我们把结果输入到 Softmax 函数
'''
m_softm = nn.Softmax(dim=1)
probs = m_softm(outputs_try)
vals_try,pred_try = torch.max(probs,dim=1)
print( 'prob sum: ', torch.sum(probs,1))
print( 'vals_try: ', vals_try)
print( 'pred_try: ', pred_try)
print([dic_imagenet[i] for i in pred_try.data])
imshow(torchvision.utils.make_grid(inputs_try.data.cpu()),
title=[dset_classes[x] for x in labels_try.data.cpu()])
最後の層を変更し、前の層のパラメータをフリーズします。VGG
モデルは次の図に示されています。ネットワークは 3 つの要素で構成されていることに注意してください。
- 畳み込み層 (CONV) は、画像内の局所的なパターンを見つけることです。
- 完全接続層 (FC) は、機能の関連付けをグローバルに確立します。
- プーリング (Pool) は、特徴の不変性を向上させるために画像の次元を削減することです。
VGG の目標は、事前トレーニングされたモデルを使用することなので、最後の nn.Linear レイヤーを 1000 クラスから 2 クラスに置き換える必要があります。トレーニング中に前のレイヤーのパラメーターをフリーズするには、required_grad=False を設定する必要があります。このようにして、トレーニング勾配を逆伝播するときに、前の層の重みは自動的に更新されません。トレーニング中は、最後の層のパラメーターのみが更新されます。
print(model_vgg)
model_vgg_new = model_vgg;
for param in model_vgg_new.parameters():
param.requires_grad = False
model_vgg_new.classifier._modules['6'] = nn.Linear(4096, 2)
model_vgg_new.classifier._modules['7'] = torch.nn.LogSoftmax(dim = 1)
model_vgg_new = model_vgg_new.to(device)
print(model_vgg_new.classifier)
完全接続層のトレーニングとテストには 3 つのステップが含まれます: ステップ 1、損失関数とオプティマイザーの作成、ステップ 2、モデルのトレーニング、ステップ 3、モデルのテスト。
'''
第一步:创建损失函数和优化器
损失函数 NLLLoss() 的 输入 是一个对数概率向量和一个目标标签.
它不会为我们计算对数概率,适合最后一层是log_softmax()的网络.
'''
criterion = nn.NLLLoss()
# 学习率
lr = 0.001
# 随机梯度下降
optimizer_vgg = torch.optim.SGD(model_vgg_new.classifier[6].parameters(),lr = lr)
'''
第二步:训练模型
'''
def train_model(model,dataloader,size,epochs=1,optimizer=None):
model.train()
for epoch in range(epochs):
running_loss = 0.0
running_corrects = 0
count = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
outputs = model(inputs)
loss = criterion(outputs,classes)
optimizer = optimizer
optimizer.zero_grad()
loss.backward()
optimizer.step()
_,preds = torch.max(outputs.data,1)
# statistics
running_loss += loss.data.item()
running_corrects += torch.sum(preds == classes.data)
count += len(inputs)
print('Training: No. ', count, ' process ... total: ', size)
epoch_loss = running_loss / size
epoch_acc = running_corrects.data.item() / size
print('Loss: {:.4f} Acc: {:.4f}'.format(
epoch_loss, epoch_acc))
# 模型训练
train_model(model_vgg_new,loader_train,size=dset_sizes['train'], epochs=1,
optimizer=optimizer_vgg)
def test_model(model,dataloader,size):
model.eval()
predictions = np.zeros(size)
all_classes = np.zeros(size)
all_proba = np.zeros((size,2))
i = 0
running_loss = 0.0
running_corrects = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
outputs = model(inputs)
loss = criterion(outputs,classes)
_,preds = torch.max(outputs.data,1)
# statistics
running_loss += loss.data.item()
running_corrects += torch.sum(preds == classes.data)
predictions[i:i+len(classes)] = preds.to('cpu').numpy()
all_classes[i:i+len(classes)] = classes.to('cpu').numpy()
all_proba[i:i+len(classes),:] = outputs.data.to('cpu').numpy()
i += len(classes)
print('Testing: No. ', i, ' process ... total: ', size)
epoch_loss = running_loss / size
epoch_acc = running_corrects.data.item() / size
print('Loss: {:.4f} Acc: {:.4f}'.format(
epoch_loss, epoch_acc))
return predictions, all_proba, all_classes
predictions, all_proba, all_classes = test_model(model_vgg_new,loader_valid,size=dset_sizes['valid'])
最後に、可視化モデルの予測結果 (主観分析)
主観分析は、予測結果と対応するテスト画像を出力します 一般的に、次の 4 つの方法があります: 予測された
正しい画像をランダムに表示する 予測が
間違っている画像をランダムに表示する
予測は正しい 、
予測誤差と確率が大きい画像
最も不確かな画像、たとえば予測確率が 0.5 に近い画像
# 单次可视化显示的图片个数
n_view = 8
correct = np.where(predictions==all_classes)[0]
from numpy.random import random, permutation
idx = permutation(correct)[:n_view]
print('random correct idx: ', idx)
loader_correct = torch.utils.data.DataLoader([dsets['valid'][x] for x in idx],
batch_size = n_view,shuffle=True)
for data in loader_correct:
inputs_cor,labels_cor = data
# Make a grid from batch
out = torchvision.utils.make_grid(inputs_cor)
imshow(out, title=[l.item() for l in labels_cor])
# 类似的思路,可以显示错误分类的图片,这里不再重复代码
まとめ
1. 残差学習の基本原理?
残差在数理统计中是指实际观察值于估计值(拟合值)之间的差。
残差网络的思想就是将网络学习的映射从X到Y转为学习从X到Y-X的差,
然后把学习到的残差信息加到原来的输出上即可。
2. バッチ正規化の原則、BN、LN、IN の主な違いについて考える。
Batch Normailization(批归一化)是深度学习中非常重要的一个概念,它是一种优化深度神经网络训练的技术,可以加速训练过程,提高模型的准确性。
Batch Normailization的原理是在进行深度神经网络的训练时,每一层的输入都会受到上一层输出的影响而发生变化,使得输入的均值和方差发生变化。
这样,每一层的输出都不再具有稳定性,容易发生梯度消失和梯度爆炸的问题。而BN通过对每个mini-batch的输出进行归一化,使得每一层的输出都具有稳定性,避免上述问题的发生。
具体来说,BN就是在每个mini-batch上对数据进行归一化,将数据按照均值和方差进行标准化,使得数据的均值为0,方差为1.
BN计算均值和标准差时,固定channel(在一个channel内),对HW和batch作平均。
LN计算均值和标准差时,固定batch(在同一个样本内),对HW和channel作平均。
IN计算均值和标准差时,同时固定channel和batch(在同一个样本的一个channel内),对HW作平均。
3. グループ畳み込みによって精度が向上するのはなぜですか? グループ畳み込みによって精度が向上し、計算量が削減できるので、スコアの数をできるだけ多くできないでしょうか。
分组卷积可以减少运算量和参数量,相同输入输出大小的情况下,减少为原来的1/g。
分组卷积可以隔绝不同组的信息交换。
在某些情况下,如每个输出与输入的一部分特征图相关联时,分组卷积可以取得比常规卷积更好的性能,如输出通道为2。但对于需要考虑所有输入特征图信息的情况,分组卷积会降低模型的性能。