前面做了模型訓練與驗證,我們會發現,模型在訓練集、測試集的準確性並不一致,主要是因爲存在泛化誤差。
深度學習中常用於應對過擬合問題的方法:權重衰減和丟棄法(dropout)
Ten Techniques Learned From fast.ai中提到一些深度學習模型訓練過程常用於應對過擬合問題的方法:合適的學習率、測試時增強(TTA)
1 權重衰減
1.1 基本內容
權重衰減即L2範數正則化,是在損失函數基礎上加入權重參數平方和,以懲罰絕對值較大的權重參數項。那麼在小批量隨機梯度下降中,線性迴歸損失函數的權重更新變成了權重參數乘懲罰因子的式子:L2範數正則化令權重w1和w2先自乘小於1的數,再減去不含懲罰項的梯度。隨着訓練進行,權重衰減,從而可能抑制過擬合。
下圖是原始權重更新步驟
添加L2正則化項後,如圖所示
1.2 Pytorch實現
直接在構造優化器實例時通過weight_decay 指定權重衰減超參數wd,默認情況下Pytorch對權重w和偏差b同時衰減,因此可以分別對權重和偏差構造優化器實例,從而只對權重衰減。
def fit_and_plot_pytorch(wd):
# 對權重參數衰減。
net = nn.Linear(num_inputs, 1)
nn.init.normal_(net.weight, mean=0, std=1)
nn.init.normal_(net.bias, mean=0, std=1)
optimizer_w = torch.optim.SGD(params=[net.weight], lr=lr,
weight_decay=wd) # 對權重參數衰減
optimizer_b = torch.optim.SGD(params=[net.bias], lr=lr) # 對偏差參數衰減
train_ls, test_ls = [], []
for _ in range(num_epochs):
for X, y in train_iter:
l = loss(net(X), y).mean()
optimizer_w.zero_grad()
optimizer_b.zero_grad()
l.backward()
# 對兩個optimizer實例分別調用step函數,從而分別更新權重和偏差
optimizer_w.step()
optimizer_b.step()
train_ls.append(loss(net(train_features),
train_labels).mean().item())
test_ls.append(loss(net(test_features),
test_labels).mean().item())
semilogy(range(1, num_epochs + 1), train_ls, 'epochs','loss',range(1, num_epochs + 1), test_ls, ['train','test'])
print('L2 norm of w:', net.weight.data.norm().item())
2 倒置丟棄法(Dropout)
2.1 基本內容
隨機丟棄隱藏層中的某些神經元,避免了輸出層過度依賴某個神經元,從而在訓練過程中起到正則化作用,從而減少過擬合的發生。涉及到的超參數是丟棄概率。
- 在測試模型中,一般不使用丟棄法。
- 一般情況,在全連接層部分,採用較大概率的dropout而在卷積層採用低概率或者不採用dropout。
2.2 Pytorch實現
def train_ch3(net, train_iter, test_iter, loss, num_epochs,batch_size,params=None, lr=None, optimizer=None):
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
for X, y in train_iter:
y_hat = net(X)
l = loss(y_hat, y).sum()
# 梯度清零
if optimizer is not None:
optimizer.zero_grad()
elif params is not None and params[0].grad is not None:
for param in params:
param.grad.data.zero_()
l.backward()
if optimizer is None:
d2l.sgd(params, lr, batch_size)
else:
optimizer.step() #
train_l_sum += l.item()
train_acc_sum += (y_hat.argmax(dim=1) ==
y).sum().item()
n += y.shape[0]
test_acc = evaluate_accuracy(test_iter, net)
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
% (epoch + 1, train_l_sum / n, train_acc_sum / n,
test_acc))
# 模型
net = nn.Sequential(
d2l.FlattenLayer(),
nn.Linear(num_inputs, num_hiddens1),
nn.ReLU(),
nn.Dropout(drop_prob1),#以指定的丟棄概率隨機丟棄上一層輸出元素
nn.Linear(num_hiddens1, num_hiddens2),
nn.ReLU(),
nn.Dropout(drop_prob2),#以指定的丟棄概率隨機丟棄上一層輸出元素
nn.Linear(num_hiddens2, 10)
)
#參數初始化
for param in net.parameters():
nn.init.normal_(param, mean=0, std=0.01)
#定義優化器
optimizer = torch.optim.SGD(net.parameters(), lr=0.5)
#訓練
train_ch3(net, train_iter, test_iter, loss, num_epochs,batch_size, None, None, optimizer)
3 合適的學習率
在Cyclical Learning Rates方法中,首先使用較低學習率來訓練神經網絡,並在每個批次中以指數形式增加學習率,然後找出學習率最高且Loss值仍在下降的拐點確定最佳學習率。在下面的情況中,最佳學習率將爲0.01。
4 測試集數據擴增
4.1 基本內容
測試時增強(test time augmentation, TTA):測試樣本原始圖像造出多個不同版本(包括不同區域裁剪和更改縮放程度等,比如tta=3),並將它們輸入到模型中;然後對多個版本進行多次預測,並平均作爲圖像的最終輸出分數。
這種技術很有效,因爲測試樣本原始圖像顯示的區域可能會缺少一些重要特徵,在模型中輸入圖像的多個版本並取平均值,能解決上述問題。
4.2 Pytorch實現
def predict(test_loader, model, tta=3):
model.eval()
test_pred_tta = 0
# TTA 次數
for _ in range(tta):
test_pred = []
with torch.no_grad():
for i, (input, target) in enumerate(test_loader):
c0, c1, c2, c3, c4, c5 = model(data[0])
output = np.concatenate([c0.data.numpy(), c1.data.numpy(),
c2.data.numpy(), c3.data.numpy(),
c4.data.numpy(), c5.data.numpy()], axis=1)
test_pred.append(output)
test_pred = np.vstack(test_pred)
test_pred_tta += test_pred
test_pred_tta /= tta
return test_pred_tta
# 測試集
test_path = glob.glob('../input/test_a/*.png')
test_path.sort()
test_label = [[1]] * len(test_path)
print(len(val_path), len(val_label))
# 測試集Loader TTA
test_loader = torch.utils.data.DataLoader(
SVHNDataset(test_path, test_label,
transforms.Compose([
transforms.Resize((64, 128)),
transforms.RandomCrop((60, 120)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])),
batch_size=40,
shuffle=False,
num_workers=0,
)
test_predict_label = predict(test_loader, model, tta=3)
參考
《動手學深度學習》
稱霸Kaggle的十大深度學習技巧
Ten Techniques Learned From fast.ai
Datawhale 零基礎入門CV - Basline