前言
在使用神經(jīng)網(wǎng)絡(luò)進行模型訓練的時候,我們可以通過誤差損失函數(shù)、精度等一系列指標來判斷最終神經(jīng)網(wǎng)絡(luò)的擬合效果,一般的問題中,無論是回歸還是擬合,本質(zhì)上都是“一個擬合過程”,我們一定特別希望知道,網(wǎng)絡(luò)每訓練一次,這個你和到底到達了一個什么程度,距離我的真實數(shù)據(jù)差別還有多少,本文通過一個簡單的例子來實現(xiàn)這樣的功能,動態(tài)展示網(wǎng)絡(luò)擬合的程度。
目錄
一、最終效果圖展示
二、實驗案例
2.1 開發(fā)環(huán)境以及要求
2.2 訓練數(shù)據(jù)的產(chǎn)生
2.3 網(wǎng)絡(luò)的結(jié)構(gòu)
三、網(wǎng)絡(luò)的搭建與模型訓練
3.1 網(wǎng)絡(luò)的定義以及實現(xiàn)
3.2 訓練模型保存
3.3 模型的搭建和保存代碼
四、完整代碼以及最終效果展示
一、最終效果圖展示
二、實驗案例
2.1 開發(fā)環(huán)境以及要求
本文神經(jīng)網(wǎng)絡(luò)的搭建使用的是keras開發(fā)框架,繪制動態(tài)圖使用的是matplotlib繪圖庫。
2.2 訓練數(shù)據(jù)的產(chǎn)生
由于本文所搭建的網(wǎng)絡(luò)很小,只是為了展示如何動態(tài)展示訓練過程,所以以一個標準正弦函數(shù)作為擬合基礎(chǔ),在一個正弦波函數(shù)上選擇了20組數(shù)據(jù)作為訓練,本文只展示,所以什么驗證、測試等工作均沒有進行。
----------------------------------------------
已知下面采樣自Sin函數(shù)的數(shù)據(jù):
x y
1 0.093 -0.81
2 0.58 -0.45
3 1.04 -0.007
4 1.55 0.48
5 2.15 0.89
6 2.62 0.997
7 2.71 0.995
8 2.73 0.993
9 3.03 0.916
10 3.14 0.86
11 3.58 0.57
12 3.66 0.504
13 3.81 0.369
14 3.83 0.35
15 4.39 -0.199
16 4.44 -0.248
17 4.6 -0.399
18 5.39 -0.932
19 5.54 -0.975
20 5.76 -0.999
----------------------------------------------
2.3 網(wǎng)絡(luò)的結(jié)構(gòu)
從上面的樣本數(shù)據(jù)可以得知,本文的網(wǎng)絡(luò)中,輸入的特征就是一個x,輸出值是一個y,所以本次網(wǎng)絡(luò)的輸入節(jié)點為1、輸出節(jié)點也是1、中間的隱藏層神經(jīng)元為10,當然這個隱藏層神經(jīng)元這里是可以隨便設(shè)置的,最終的網(wǎng)絡(luò)結(jié)構(gòu)如下:
本文最終要做的事就是,通過一個簡單的三層神經(jīng)網(wǎng)絡(luò)訓練一個Sin函數(shù)的擬合器,并可視化模型訓練過程的擬合曲線。
三、網(wǎng)絡(luò)的搭建與模型訓練
3.1 網(wǎng)絡(luò)的定義以及實現(xiàn)
import math;
import random;
from matplotlib import pyplot as plt
from keras.models import Sequential
from keras.layers.core import Dense
from keras.optimizers import Adam
import numpy as np
from keras.callbacks import ModelCheckpoint
import os
#采樣函數(shù)
def sample(low, up, num):
data = [];
for i in range(num):
#采樣
tmp = random.uniform(low, up);
data.append(tmp);
data.sort();
return data;
#sin函數(shù)
def func(x):
y = [];
for i in range(len(x)):
tmp = math.sin(x[i] - math.pi/3);
y.append(tmp);
return y;
#獲取模型擬合結(jié)果
def getfit(model,x):
y = [];
for i in range(len(x)):
tmp = model.predict([x[i]], 10);
y.append(tmp[0][0]);
return y;
#刪除同一目錄下的所有文件
def del_file(path):
ls = os.listdir(path)
for i in ls:
c_path = os.path.join(path, i)
if os.path.isdir(c_path):
del_file(c_path)
else:
os.remove(c_path)
if __name__ == '__main__':
path = 'E:/Model/';
del_file(path);
low = 0;
up = 2 * math.pi;
x = np.linspace(low, up, 1000);
y = func(x);
# 數(shù)據(jù)采樣
# x_sample = sample(low,up,20);
x_sample = [0.09326442022999694, 0.5812590520508311, 1.040490143783586, 1.5504427746047338, 2.1589557183817036, 2.6235357787018407, 2.712578091093361, 2.7379109336528167, 3.0339662651841186, 3.147676812083248, 3.58596337171837, 3.6621496731124314, 3.81130899864203, 3.833092859928872, 4.396611340802901, 4.4481080339256875, 4.609657879057151, 5.399731063412583, 5.54299720786794, 5.764084730699906];
y_sample = func(x_sample);
# callback
filepath='E:/Model/weights-improvement-{epoch:00d}.hdf5';
checkpoint= ModelCheckpoint(filepath, verbose=1, save_best_only=False, mode='max');
callbacks_list= [checkpoint];
# 建立順序神經(jīng)網(wǎng)絡(luò)層次模型
model = Sequential();
model.add(Dense(10, input_dim=1, init='uniform', activation='relu'));
model.add(Dense(1, init='uniform', activation='tanh'));
adam = Adam(lr = 0.05);
model.compile(loss='mean_squared_error', optimizer=adam, metrics=['accuracy']);
model.fit(x_sample, y_sample, nb_epoch=1000, batch_size=20,callbacks=callbacks_list);
#測試數(shù)據(jù)
x_new = np.linspace(low, up, 1000);
y_new = getfit(model,x_new);
# 數(shù)據(jù)可視化
plt.plot(x,y);
plt.scatter(x_sample, y_sample);
plt.plot(x_new,y_new);
plt.show();
3.2 訓練模型保存
在神經(jīng)網(wǎng)絡(luò)訓練的過程中,有一個非常重要的操作,就是將訓練過程中模型的參數(shù)保存到本地,這是后面擬合過程可視化的基礎(chǔ)。訓練過程中保存的模型文件,如下圖所示。
模型保存的關(guān)鍵在于fit函數(shù)中callback函數(shù)的設(shè)置,注意到,下面的代碼,每次迭代,算法都會執(zhí)行callbacks函數(shù)指定的函數(shù)列表中的方法。這里,我們的回調(diào)函數(shù)設(shè)置為ModelCheckpoint,其參數(shù)如下表所示:
參數(shù)的含義
(1)filename: 字符串,保存模型的路徑
(2)verbose: 0或1
(3)mode: ‘a(chǎn)uto’,‘min’,‘max’
(4)monitor: 需要監(jiān)視的值
(5)save_best_only: 當設(shè)置為True時,監(jiān)測值有改進時才會保存當前的模型。在save_best_only=True時決定性能最佳模型的評判準則,例如,當監(jiān)測值為val_acc時,模式應(yīng)為max,當監(jiān)測值為val_loss時,模式應(yīng)為min。在auto模式下,評價準則由被監(jiān)測值的名字自動推斷
(6)save_weights_only: 若設(shè)置為True,則只保存模型權(quán)重,否則將保存整個模型(包括模型結(jié)構(gòu),配置信息等)
(7)period CheckPoint之間的間隔的epoch數(shù)
3.3 模型的搭建和保存代碼
# callback
filepath='E:/Model/weights-improvement-{epoch:00d}.hdf5';
checkpoint= ModelCheckpoint(filepath, verbose=1, save_best_only=False, mode='max');
callbacks_list= [checkpoint];
# 建立順序神經(jīng)網(wǎng)絡(luò)層次模型
model = Sequential();
model.add(Dense(10, input_dim=1, init='uniform', activation='relu'));
model.add(Dense(1, init='uniform', activation='tanh'));
adam = Adam(lr = 0.05);
model.compile(loss='mean_squared_error', optimizer=adam, metrics=['accuracy']);
model.fit(x_sample, y_sample, nb_epoch=1000, batch_size=20,callbacks=callbacks_list);
四、完整代碼以及最終效果展示
import math;
import random;
from matplotlib import pyplot as plt
from keras.models import Sequential
from keras.layers.core import Dense
import numpy as np
import matplotlib.animation as animation
from PIL import Image
#定義kdd99數(shù)據(jù)預(yù)處理函數(shù)
def sample(low, up, num):
data = [];
for i in range(num):
#采樣
tmp = random.uniform(low, up);
data.append(tmp);
data.sort();
return data;
def func(x):
y = [];
for i in range(len(x)):
tmp = math.sin(x[i] - math.pi/3);
y.append(tmp);
return y;
def getfit(model,x):
y = [];
for i in range(len(x)):
tmp = model.predict([x[i]], 10);
y.append(tmp[0][0]);
return y;
def init():
fpath = 'E:/imgs/0.jpg';
img = Image.open(fpath);
plt.axis('off') # 關(guān)掉坐標軸為 off
return plt.imshow(img);
def update(i):
fpath = 'E:/imgs/' + str(i) + '.jpg';
img = Image.open(fpath);
plt.axis('off') # 關(guān)掉坐標軸為 off
return plt.imshow(img);
if __name__ == '__main__':
low = 0;
up = 2 * math.pi;
x = np.linspace(low, up, 1000);
y = func(x);
# 數(shù)據(jù)采樣
# x_sample = sample(low,up,20);
x_sample = [0.09326442022999694, 0.5812590520508311, 1.040490143783586, 1.5504427746047338, 2.1589557183817036, 2.6235357787018407, 2.712578091093361, 2.7379109336528167, 3.0339662651841186, 3.147676812083248, 3.58596337171837, 3.6621496731124314, 3.81130899864203, 3.833092859928872, 4.396611340802901, 4.4481080339256875, 4.609657879057151, 5.399731063412583, 5.54299720786794, 5.764084730699906];
y_sample = func(x_sample);
# 建立順序神經(jīng)網(wǎng)絡(luò)層次模型
model = Sequential();
model.add(Dense(10, input_dim=1, init='uniform', activation='relu'));
model.add(Dense(1, init='uniform', activation='tanh'));
plt.ion(); #開啟interactive mode 成功的關(guān)鍵函數(shù)
fig = plt.figure(1);
for i in range(100):
filepath='E:/Model/weights-improvement-' + str(i + 1) + '.hdf5';
model.load_weights(filepath);
#測試數(shù)據(jù)
x_new = np.linspace(low, up, 1000);
y_new = getfit(model,x_new);
# 顯示數(shù)據(jù)
plt.clf();
plt.plot(x,y);
plt.scatter(x_sample, y_sample);
plt.plot(x_new,y_new);
ffpath = 'E:/imgs/' + str(i) + '.jpg';
plt.savefig(ffpath);
plt.pause(0.01) # 暫停0.01秒
ani = animation.FuncAnimation(plt.figure(2), update,range(100),init_func=init, interval=500);
ani.save('E:/test.gif',writer='pillow');
plt.ioff() # 關(guān)閉交互模式
最終的結(jié)果展示為如下: