訓練神經網絡還可以用「聽」的!
網友做了一個非常有趣的實驗:將每個神經網絡層梯度範式轉換成了一個音調,這樣人類就可以憑藉聽覺,來很好的分辨出非常小的幹擾,比如節奏和音調。
以往,我們在訓練神經網絡的時候,通常會測量許多不同的指標,例如精度、損失以及梯度等等。這些工作大部分是在TensorBoard上聚合上述度量指標並且繪製可視化。
但除了視覺之外,有Reddit網友提出:用聽覺也可以監控神經網絡的訓練!
博客地址:
http://blog.christianperone.com/2019/08/listening-to-the-neural-network-gradient-norms-during-training/
聲音是目前神經網絡訓練中研究較少的一個方向。人類的聽覺可以很好的分辨出非常小的幹擾(即使這些幹擾時間很短或很細微),比如節奏和音高。
在這個實驗中,研究者做了一個非常簡單的例子,顯示了使用每層的梯度範數進行的合成聲音,以及使用不同設置(如不同學習率、優化器,動量等)對MNIST進行卷積神經網絡訓練的步驟等。
看到這個結果,Reddit網友嗨了,紛紛開發腦洞。
MLApprentice:
這真太了不起了。我一直在尋找直觀體驗漸變的方法,我覺得只看直方圖時很難注意到訓練模式。你有沒有想過用圖層深度來控制音高並使用音量來表示規範呢?這樣我們光靠聽音高就能知道是第幾層了。klaysDoodle:
MLApprentice:
樓上你太搞笑了。你可以將深度標準化,使其保持在人類聽覺範圍內就可以。gohu_cd:
很有意思!我想知道這是否有助於調試神經網絡訓練。因為其中存在不同的加權損失,甚至是對抗的(例如GAN)。因為視覺和聽覺都是感官,查看圖表或聽覺聲音應該具有相同數量的信息。可以用對應於加權梯度的所有聲音創建一個「交響樂」,也許這對於確定每個損失的正確權重是有用的。在下文給出的實驗中,你需要安裝PyAudio和PyTorch來運行代碼。
如下訓練神經網絡的聲音可跳轉至下方連結聽:
http://blog.christianperone.com/2019/08/listening-to-the-neural-network-gradient-norms-during-training/
用LR 0.01和SGD訓練聲音
下面這個音頻片段表示在第一個epoch的前200步中使用4個層的梯度,並使用10個batche大小的訓練會話。音高越高,一個神經網絡層的標準值就越高,不同的batche之間會有短暫的靜音。
用LR 0.1的SGD訓練聲音
同上,但是學習率更高了。
用LR 1.0的SGD訓練聲音
同上,但是隨著學習率的提高,神經網絡產生發散(diverge)。
用LR 1.0、BS 256的SGD訓練聲音
設置是相同的,但是學習率高達1.0,batche大小為256。
用LR 0.01的Adam訓練聲音
與SGD的設置相同,但使用的是Adam。
以下是實驗的全部原始碼,有興趣的讀者可以上手試一下。
1import pyaudio
2import numpy as np
3import wave
4
5import torch
6import torch.nn as nn
7import torch.nn.functional as F
8import torch.optim as optim
9from torchvision import datasets, transforms
10
11
12class Net(nn.Module):
13 def __init__(self):
14 super(Net, self).__init__()
15 self.conv1 = nn.Conv2d(1, 20, 5, 1)
16 self.conv2 = nn.Conv2d(20, 50, 5, 1)
17 self.fc1 = nn.Linear(4*4*50, 500)
18 self.fc2 = nn.Linear(500, 10)
19
20 self.ordered_layers = [self.conv1,
21 self.conv2,
22 self.fc1,
23 self.fc2]
24
25 def forward(self, x):
26 x = F.relu(self.conv1(x))
27 x = F.max_pool2d(x, 2, 2)
28 x = F.relu(self.conv2(x))
29 x = F.max_pool2d(x, 2, 2)
30 x = x.view(-1, 4*4*50)
31 x = F.relu(self.fc1(x))
32 x = self.fc2(x)
33 return F.log_softmax(x, dim=1)
34
35
36def open_stream(fs):
37 p = pyaudio.PyAudio()
38 stream = p.open(format=pyaudio.paFloat32,
39 channels=1,
40 rate=fs,
41 output=True)
42 return p, stream
43
44
45def generate_tone(fs, freq, duration):
46 npsin = np.sin(2 * np.pi * np.arange(fs*duration) * freq / fs)
47 samples = npsin.astype(np.float32)
48 return 0.1 * samples
49
50
51def train(model, device, train_loader, optimizer, epoch):
52 model.train()
53
54 fs = 44100
55 duration = 0.01
56 f = 200.0
57 p, stream = open_stream(fs)
58
59 frames = []
60
61 for batch_idx, (data, target) in enumerate(train_loader):
62 data, target = data.to(device), target.to(device)
63 optimizer.zero_grad()
64 output = model(data)
65 loss = F.nll_loss(output, target)
66 loss.backward()
67
68 norms = []
69 for layer in model.ordered_layers:
70 norm_grad = layer.weight.grad.norm()
71 norms.append(norm_grad)
72
73 tone = f + ((norm_grad.numpy()) * 100.0)
74 tone = tone.astype(np.float32)
75 samples = generate_tone(fs, tone, duration)
76
77 frames.append(samples)
78
79 silence = np.zeros(samples.shape[0] * 2,
80 dtype=np.float32)
81 frames.append(silence)
82
83 optimizer.step()
84
85
86 if batch_idx == 200:
87 break
88
89 wf = wave.open("sgd_lr_1_0_bs256.wav", 'wb')
90 wf.setnchannels(1)
91 wf.setsampwidth(p.get_sample_size(pyaudio.paFloat32))
92 wf.setframerate(fs)
93 wf.writeframes(b''.join(frames))
94 wf.close()
95
96 stream.stop_stream()
97 stream.close()
98 p.terminate()
99
100
101def run_main():
102 device = torch.device("cpu")
103
104 train_loader = torch.utils.data.DataLoader(
105 datasets.MNIST('../data', train=True, download=True,
106 transform=transforms.Compose([
107 transforms.ToTensor(),
108 transforms.Normalize((0.1307,), (0.3081,))
109 ])),
110 batch_size=256, shuffle=True)
111
112 model = Net().to(device)
113 optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
114
115 for epoch in range(1, 2):
116 train(model, device, train_loader, optimizer, epoch)
117
118
119if __name__ == "__main__":
120 run_main()
Reddit地址:
https://www.reddit.com/r/MachineLearning/comments/clyzgx/p_listening_to_the_neural_network_gradient_norms/
博客:
http://blog.christianperone.com/2019/08/listening-to-the-neural-network-gradient-norms-during-training/