搭建模型
这个模型很简单,一个双层的神经网络,第一层后面接一个Sigmoid激活函数,第二层直接输出拟合数据,如图14-2所示。

def model():dataReader = LoadData()num_input = 1num_hidden1 = 4num_output = 1max_epoch = 10000batch_size = 10learning_rate = 0.5params = 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=449999loss_train=0.000920, accuracy_train=0.968329loss_valid=0.000839, accuracy_valid=0.962375time used: 28.002626419067383save parameterstotal weights abs sum= 45.27530164993504total weights = 8little weights = 0zero weights = 0testing...0.98178145506870210.9817814550687021
由于我们设置了eps=0.001,所以在5000多个epoch时便达到了要求,训练停止。最后用测试集得到的准确率为98.17%,已经非常不错了。如果训练更多的轮,可以得到更好的结果。
代码位置
原代码位置:ch14, Level1
个人代码:dnn_regression**
keras实现
from HelperClass2.MnistImageDataReader import *from keras.models import Sequentialfrom keras.layers import Denseimport matplotlib.pyplot as pltimport osos.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.YTrainx_test, y_test = dataReader.XTest, dataReader.YTestx_val, y_val = dataReader.XDev, dataReader.YDevreturn x_train, y_train, x_test, y_test, x_val, y_valdef 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.01936031475663185weights: [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)]
模型损失曲线

