搭建模型
这个模型很简单,一个双层的神经网络,第一层后面接一个Sigmoid激活函数,第二层直接输出拟合数据,如图14-2所示。
def model():
dataReader = LoadData()
num_input = 1
num_hidden1 = 4
num_output = 1
max_epoch = 10000
batch_size = 10
learning_rate = 0.5
params = HyperParameters_4_0(
learning_rate, max_epoch, batch_size,
net_type=NetType.Fitting,
init_method=InitialMethod.Xavier,
stopper=Stopper(StopCondition.StopLoss, 0.001))
net = NeuralNet_4_0(params, "Level1_CurveFittingNet")
fc1 = FcLayer_1_0(num_input, num_hidden1, params)
net.add_layer(fc1, "fc1")
sigmoid1 = ActivationLayer(Sigmoid())
net.add_layer(sigmoid1, "sigmoid1")
fc2 = FcLayer_1_0(num_hidden1, num_output, params)
net.add_layer(fc2, "fc2")
net.train(dataReader, checkpoint=100, need_test=True)
net.ShowLossHistory()
ShowResult(net, dataReader)
超参数说明:
- 输入层1个神经元,因为只有一个x值
- 隐层4个神经元,对于此问题来说应该是足够了,因为特征很少
- 输出层1个神经元,因为是拟合任务
- 学习率=0.5
- 最大epoch=10000轮
- 批量样本数=10
- 拟合网络类型
- Xavier初始化
- 绝对损失停止条件=0.001
训练结果
如图14-3所示,损失函数值在一段平缓期过后,开始陡降,这种现象在神经网络的训练中是常见的,最有可能的是当时处于一个梯度变化的平缓地带,算法在艰难地寻找下坡路,然后忽然就找到了。这种情况同时也带来一个弊端:我们会经常遇到缓坡,到底要不要还继续训练?是不是再坚持一会儿就能找到出路呢?抑或是模型能力不够,永远找不到出路呢?这个问题没有准确答案,只能靠试验和经验了。
图14-4左侧子图是拟合的情况,绿色点是测试集数据,红色点是神经网路的推理结果,可以看到除了最左侧开始的部分,其它部分都拟合的不错。注意,这里我们不是在讨论过拟合、欠拟合的问题,我们在这个章节的目的就是更好地拟合一条曲线。
图14-4右侧的子图是用下面的代码生成的:
y_test_real = net.inference(dr.XTest)
axes.scatter(y_test_real, y_test_real-dr.YTestRaw, marker='o')
以测试集的真实值为横坐标,以真实值和预测值的差为纵坐标。最理想的情况是所有点都在y=0处排成一条横线。从图上看,真实值和预测值二者的差异明显,但是请注意横坐标和纵坐标的间距相差一个数量级,所以差距其实不大。
再看打印输出的最后部分:
epoch=4999, total_iteration=449999
loss_train=0.000920, accuracy_train=0.968329
loss_valid=0.000839, accuracy_valid=0.962375
time used: 28.002626419067383
save parameters
total weights abs sum= 45.27530164993504
total weights = 8
little weights = 0
zero weights = 0
testing...
0.9817814550687021
0.9817814550687021
由于我们设置了eps=0.001,所以在5000多个epoch时便达到了要求,训练停止。最后用测试集得到的准确率为98.17%,已经非常不错了。如果训练更多的轮,可以得到更好的结果。
代码位置
原代码位置:ch14, Level1
个人代码:dnn_regression**
keras实现
from HelperClass2.MnistImageDataReader import *
from keras.models import Sequential
from keras.layers import Dense
import matplotlib.pyplot as plt
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
def load_data():
train_file = "../data/ch09.train.npz"
test_file = "../data/ch09.test.npz"
dataReader = DataReader_2_0(train_file, test_file)
dataReader.ReadData()
# dr.NormalizeX()
# dr.NormalizeY(YNormalizationMethod.Regression)
dataReader.Shuffle()
dataReader.GenerateValidationSet()
x_train, y_train = dataReader.XTrain, dataReader.YTrain
x_test, y_test = dataReader.XTest, dataReader.YTest
x_val, y_val = dataReader.XDev, dataReader.YDev
return x_train, y_train, x_test, y_test, x_val, y_val
def build_model():
model = Sequential()
model.add(Dense(4, activation='sigmoid', input_shape=(1, )))
model.add(Dense(1, activation='linear'))
model.compile(optimizer='Adam',
loss='mean_squared_error')
return model
#画出训练过程中训练和验证的精度与损失
def draw_train_history(history):
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()
if __name__ == '__main__':
x_train, y_train, x_test, y_test, x_val, y_val = load_data()
# print(x_train.shape)
# print(x_test.shape)
# print(x_val.shape)
model = build_model()
history = model.fit(x_train, y_train, epochs=50, batch_size=10, validation_data=(x_val, y_val))
draw_train_history(history)
loss = model.evaluate(x_test, y_test)
print("test loss: {}".format(loss))
weights = model.get_weights()
print("weights: ", weights)
模型输出
test loss: 0.01936031475663185
weights: [array([[-0.0498461, -0.8130934, 0.694032 , 1.5218066]], dtype=float32), array([ 0.23504476, 0.23763067, -0.1935111 , -0.6370921 ], dtype=float32), array([[-0.5563479 ],
[-0.6319033 ],
[ 0.20091562],
[ 0.9161764 ]], dtype=float32), array([-0.14805052], dtype=float32)]
模型损失曲线