訓練網路時為什麼會出現loss逐漸增大的情況?

模型找是是網上找的pytorch實現的lenet,我把訓練的次數調大了,發現訓練集loss值在50次左右前是一直減小的,但之後逐漸增大,200多次後就大到和初始偏差值差不多了,重複多次依舊。

按到道理,重複次數過多會過擬合導致結果準確度下降可以理解,但是偏差值應該是隨著訓練次數的增加逐漸收斂的啊,為什麼會越來越大呢?

transform=transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
])

trainset = torchvision.datasets.CIFAR10(root="./data", train=True, download=False, transform=transform)

trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root="./data", train=False, download=False, transform=transform)

testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=2)
classes = ("plane", "car", "bird", "cat",
"deer", "dog", "frog", "horse", "ship", "truck")

class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2,2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)

def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16*5*5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x

net = Net()

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

for epoch in range(1000):

running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# get the inputs
inputs, labels = data

# wrap them in Variable
inputs, labels = Variable(inputs), Variable(labels)

# zero the parameter gradients
optimizer.zero_grad() #將參數的grad值初始化為0

# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward() #反向傳播
optimizer.step() #用SGD更新參數

# 每2000批數據列印一次平均loss值
running_loss += loss.data[0]
if i % 2000 == 1999:
print("[%d, %5d] loss: %.3f" % (epoch+1, i+1, running_loss / 2000))
running_loss = 0.0

print("Finished Training %s"%epoch)

correct = 0
total = 0
for data in testloader:
images, labels = data
outputs = net(Variable(images))
#print outputs.data
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()

print("Accuracy of the network on the 10000 test images: %d %%" % (100 * correct / total))


如果用的sgd,可以考慮在後期對學習率進行衰減,後期學習率太大是有可能出現訓練集loss上升的情況。


你自己不都說了嗎,過擬合


根本原因還是學習率太大,建議用指數衰減的學習率或者直接調用Rmsprop,Adam等現成的優化演算法

這個loss先減小後增大的情況可以如下理解:

(原諒我的渣鼠繪`

假設loss function的勢能面如上所示(註:橫坐標為參數,縱坐標為loss值)

初始化之後,參數空間落在了箭頭所指向的的圓點處,這裡梯度比較平緩,一開始梯度下降確實可以使得loss下降

然而當梯度下降到了loss function的梯度陡峭的地方時,梯度下降的步長會變的很大,很有可能跨過loss function的谷底,而另一面的梯度如果也很大,則會導致步長越來越大,導致優化步驟不能夠收斂。

解決這個問題有一些現成的辦法,其中之一就是隨著訓練步驟的進行,對學習率乘上一個參數(0.99或者0.999)使得學習率隨著學習步驟的進行而下降。另一種辦法就是採用現成的優化演算法。

引起這種問題的根本原因是Hessian矩陣的病態條件數

假設對局部最優解處的loss function做二次近似,則有最優步長為:

epsilon = frac{g^Tg}{g^THg}

可證明在最壞的情況下(最壞的情況指病態條件數最嚴重),最佳的學習率為1/λ,其中λ為Hessian矩陣的最大的特徵值。

此時如果學習率較大,顯然會引起不能夠收斂的情況


http://www.cnblogs.com/custer/p/6349281.html

可以看下相關的部分


自己做實驗時出現過這種情況,後來把學習率調小了……但不知是不是這個原因


現在迭代到快400次了,loss值已經超過2.3遠大於初始值,這都不是梯度下降而是梯度上升了。

開始曾懷疑是SGD函數的特性使然,但是按道理講SGD應該只會使loss值收斂到一定程序時在一個值上下擺動,而不應該持續增加。難道是bug?


推薦閱讀:

學習matlab人工神經網路,哪些書籍比較好?
MATLAB神經網路工具箱中newcf 和newff的區別?
深度學習cnn圖片預處理方式,為什麼乘以0.0167?
神經網路的訓練可以採用二階優化方法嗎(如Newton, Quasi Newton)?
Hinton提出逐層貪婪訓練的方式來解決梯度彌散和局部極值的問題,caffe是如何做到的?

TAG:機器學習 | 神經網路 | 深度學習DeepLearning | 收斂 | PyTorch |