はじめに
WEBの記事を参考にニューラルネットワークに入門しようとしたら詰まり、検索ワードも分からずかなり時間を溶かしたので同じように迷う人のために記しておきます。
Qiita初投稿のため見づらいところあるかもしれませんがご容赦ください。
学習が進むにつれてロスが下が...らなかった
適当にググって出たページでサクッとニューラルネット入門しようとしたら全然ロスが下がらなかった。
for epoch in range(100):
total_loss = 0
for train_x, train_y in train_loader:
output = model(train_x)
loss = F.cross_entropy(output, train_y)
model.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.data
if (epoch+1)%10 == 0:
print(total_loss)
出力
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
tensor(9.0109)
???
学習後の重みを見ても...
print(model.fc1.weight.grad)
出力
tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
# 長いので中略(途中も全部0)
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
ワーキレイダナー
やろうとしていたこと
scikit-learnのwineのデータセットでワインの分類をしようとした。
データセット
from sklearn.datasets import load_wine
wine = load_wine()
モデル
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(13, 30)
self.fc2 = nn.Linear(30, 2) # 本来のデータセットは3種類の分類だが2種類に絞った
def forward(self, x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
return x
結論
ReLUの使い方 が悪かったみたいです
どうやらDying ReLUという現象があるようです。
重みが負の値に更新されたためにすべて0になりそれ以上逆伝播ができず重みの更新もできずという状態に陥っていたようです。
詳細は「Dying ReLU」でググると詳しい記事がいくつか出てくるのでそちらに丸投げします。(ごめんなさい)
ReLU以外の活性化関数を使うとかデータをあらかじめ正規化しておくとかすると解消しました。
まとめ
ReLUって絶対正義ではなかったんだなって思いました。(そりゃそう)
あとデータの前処理重要ですね。
とりあえず無事入門できたのでガンガン勉強してきたいと思います。