因為要用到神經網絡算法,之前接觸過一些機器學習的皮毛還是半知半解,先着手練習一些比較好了解的小項目吧,新手上路見笑了。開始:
文章目錄
- 回歸模型(keras)
-
- 一進制二次模型
- 調整與改進
-
- 階段1——修改epochs
- 階段2——修改學習率
回歸模型(keras)
一進制二次模型
先放模型:
y = x 2 + 1 y=x^2+1 y=x2+1
樣本訓練資料随機模拟就好了。引入tf庫中的keras子產品,程式小,是以要用到的函數我就直接單獨加載了:
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.initializers import Ones
import matplotlib.pyplot as plt
接下來生成200組資料樣本,加入随機噪聲,其中前160組作為訓練樣本,後40組用于測試評估網絡
X = np.linspace(-10, 10, 200)
np.random.shuffle(X) # randomize the data
Y = X * X + 1 + np.random.normal(0, 0.05, (200, ))
X_train, Y_train = X[:160], Y[:160] # train 前 160 data points
X_test, Y_test = X[160:], Y[160:] # test 後 40 data points
畫出訓練集
以及測試集
接下來建立網絡層。從這個部分開始,就要一點一點嘗試設定參數了,以下參數的調整對結果均有影響(不調整有可能也有影響orz…)
# 建立神經網絡
model = Sequential()
model.add(Dense(units=10, input_dim=1, activation='relu'))
model.add(Dense(units=10, activation='relu'))
model.add(Dense(units=1, activation='relu'))
先解釋一下這個代碼塊的含義,Sequential()函數keras子產品中的堆疊模型(簡單了解就是網絡層直接一層一層的疊加 )
add函數給這個模型增加Dense層,Dense即全連接配接層,存放每個權重的通道,這幾行函數其實建構了如下這樣一個網絡:
一進制變量X對應輸入層是一維的,這時Dense1必須要告知輸入次元
Input_dim = 1
,後面的連接配接層的input_dim參數就沒必要寫了,可以推算出來。每個dense層還要給出units個數,表示下個層的單元節個數,這裡兩個隐藏層節點數分别都為10個。這樣一來,每一層的節點數就很清楚了。激活函數選擇了"relu"。
接下來配置學習過程,損失函數選擇均方根對數誤差,優化器是SGD(随機梯度下降)參數lr是學習率,評估标準為精度值:
# 選擇損失函數和優化器
model.compile(loss='mean_squared_logarithmic_error', optimizer=SGD(lr=0.01),metrics=["accuracy"])
開始訓練,fit函數參數設定:epoch為訓練次數,verbose=0表示我不想看到訓練中輸出的每個epoch,batch_size預設為32,我沒有設定,validation_data放上測試集
# 訓練
print('Training ----------')
history = model.fit(X_train, Y_train, epochs=50, verbose=0, validation_data=(X_test, Y_test))
這一部分是可視化的部分,精度值:
# 繪制訓練 & 驗證的準确率值
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()
(好像出現了點問題,待解決。。)
損失函數:
# 繪制訓練 & 驗證的損失值
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()
(有時候這個loss函數也會居高不下)
# 評估
loss_and_metrics = model.evaluate(X_test, Y_test)
loss_and_metrics
[0.22141730785369873, 0.0]
(誤差很大,精度一直是0)
再做一個資料集預測一下
# 預測
X_pre = np.linspace(-10, 10, 200)
Y_pre = X_pre * X_pre + 1
classes = model.predict(X_pre, batch_size=7)
plt.scatter(X_pre, Y_pre)
plt.scatter(X_pre, classes)
(看得出來誤差很大。。)
調整與改進
階段1——修改epochs
epochs = 500 試一下
loss:
預測:
(???!@#¥%……&# )
重新跑一下。。。
loss:
預測:
參數沒調整的情況下也會出現全為0的問題,是否梯度下降過程中卡在局部極小點?
階段2——修改學習率
前面的成圖發現拟合的函數有了大概的雛形了,但最終曲線沒有彎曲成想要的弧度。學習樣本不足,步伐太慢,網絡太小,都有可能。先調整一下學習率,令lr = 0.1
loss:
預測:
可以看到,loss函數收斂更快了,曲線拟合效果變好了。
令 lr = 0.2
loss:
預測:
比剛剛的效果要好。
令 lr = 0.3
loss:
預測:
這次變化不是很大了,我想我應該找出一個讓它效果變差的界限。
當我把學習率加到1時,
loss:
預測:
loss函數收斂的不那麼平滑,但拟合結果更好了。
至于精度值一直為0的問題,有待解決,再去研究一下。
- 函數拟合
- 精度值的問題
------------------------------------------更新 2019/09/05------------------------------------------
回歸模型不需要用到accuracy評估,accuracy是評估分類問題的,把那部分的代碼和可視化去掉就行。
嘗試了一下把優化器SGD改成了Adam,效果很明顯:
# 選擇損失函數和優化器
model.compile(loss='mean_squared_logarithmic_error', optimizer=Adam(lr=0.1))
loss:
預測: