0.导航
项目 | 内容 |
---|---|
这个作业属于哪个课程 | 人工智能实战 |
这个作业的要求在哪里 | 人工智能实战第六次作业(个人) |
我在这个课程的目标是 | 开拓视野,积累AI实战经验 |
这个作业在哪个具体方面帮助我 | 通过调整不同参数,研究其对于神经网络性能的影响,加深对神经网络以及其各个参数的理解和认识 |
1.具体作业内容
- a. 将模型准确度调整至>97%
- b. 整理形成博客,博客中给出参数列表和对应值
- c. 给出最终的loss下降曲线
- d. 给出最终准确度结果
2.过程及代码
- I.调整隐藏层神经元数量
首先测试隐藏层神经元数量,在此选择了[32, 64, 128]和[12, 32, 64]分别作为第一层和第二层的神经元数量,一共六组进行测试并绘制图表
代码(修改主函数为main函数并且在Test函数后添加返回值返回正确率correct_rate)和结果如下:
def main(LR, NH1, NH2, ME, BS):
print("Loading...")
learning_rate = LR
n_hidden1 = NH1
n_hidden2 = NH2
n_output = 10
dataReader = LoadData(n_output)
n_images = dataReader.num_example
n_input = dataReader.num_feature
m_epoch =ME
batch_size = BS
dict_Param = InitialParameters3(n_input, n_hidden1, n_hidden2, n_output, 2)
dict_Param = Train(dataReader, learning_rate, m_epoch, n_images, n_input, n_output, dict_Param, forward3, backward3, update3, batch_size)
SaveResult(dict_Param)
correct, num_images = Test(dataReader, n_output, dict_Param, n_input, forward3)
return correct/num_images
if __name__ == '__main__':
correct_rate = []
n_hidden_list = ["32,16","64,16","128,16","64,32","128,32","128,64"]
correct_rate.append(main(0.2, 32, 16, 2, 10))
correct_rate.append(main(0.2, 64, 16, 2, 10))
correct_rate.append(main(0.2, 128, 16, 2, 10))
correct_rate.append(main(0.2, 64, 32, 2, 10))
correct_rate.append(main(0.2, 128, 32, 2, 10))
correct_rate.append(main(0.2, 128, 64, 2, 10))
plt.figure()
plt.plot(n_hidden_list, correct_rate)
plt.xlabel("n_hidden")
plt.ylabel("correct_rate")
plt.show()
最高点是n_hidden1=64, n_hidden2=32的时候,结果为rate=9645 / 10000 = 0.9645,而n_hidden1=128, n_hidden2=64时结果为rate=9630 / 10000 = 0.963
可见隐藏层的神经元数量有时候并非越多越好,而可能在某个区间内有最佳效果,过犹不及
- II.调整学习率
注意到初始化会影响没次试验的结果,因此需要排除初始化的影响
其实做第一步调n_hidden参数的时候就发现这个问题了,但是因为初始化的参数本身就有n_hidden参与所以以我的水平暂时解决不了这个问题,当然确实经过多次的运行程序得到的结果中64, 32这一组的结果并不一定是最好的,有时候128, 64更好,还有时候甚至128, 32甚至128, 16之类的都作为某次测试的最佳结果出现过,我们姑且先用128, 64来做吧
改动的代码段如下
def main(LR, NH1, NH2, ME, BS, dP):
print("Loading...")
learning_rate = LR
n_hidden1 = NH1
n_hidden2 = NH2
# n_output = 10
# dataReader = LoadData(n_output)
# n_images = dataReader.num_example
# n_input = dataReader.num_feature
m_epoch =ME
batch_size = BS
dict_Param = dP
# dict_Param = InitialParameters3(n_input, n_hidden1, n_hidden2, n_output, 2)
dict_Param = Train(dataReader, learning_rate, m_epoch, n_images, n_input, n_output, dict_Param, forward3, backward3, update3, batch_size)
SaveResult(dict_Param)
correct, num_images = Test(dataReader, n_output, dict_Param, n_input, forward3)
return correct/num_images
if __name__ == '__main__':
n_output = 10
dataReader = LoadData(n_output)
n_images = dataReader.num_example
n_input = dataReader.num_feature
dP = InitialParameters3(n_input, 128, 64, n_output, 2)
correct_rate = []
learning_rate_list = [0.05, 0.1, 0.2, 0.4, 0.8]
for i in range(5):
correct_rate.append(main(learning_rate_list[i], 128, 64, 2, 10, dP))
plt.figure()
plt.plot(learning_rate_list, correct_rate)
plt.xlabel("learning_rate")
plt.ylabel("correct_rate")
plt.show()
结果如下图
代码连续运行两次得到的结果图相等,说明基本能排除随机初始化带来的干扰(之后经过多次测试发现仍有小概率产出不同的结果图,按理说因为每次随机种子可能不一样所以数值会不一样,但每个点的大小关系应该不会变才对,然而事实上却并非如此,至于原因就不得而知了Orz)
接着缩小学习率范围提高精度,得到结果如图
learning_rate_list = [0.2, 0.3, 0.4, 0.5, 0.6]
learning_rate_list = [0.2, 0.25, 0.3, 0.35, 0.4]
因此基本可以认定学习率为0.3时,有最佳的结果
- III.调整batch_size
用同样的方式修改代码
if __name__ == '__main__':
n_output = 10
dataReader = LoadData(n_output)
n_images = dataReader.num_example
n_input = dataReader.num_feature
dP = InitialParameters3(n_input, 128, 64, n_output, 2)
correct_rate = []
batch_size_list = [2, 5, 10, 20, 30]
for i in range(5):
correct_rate.append(main(0.3, 128, 64, 2, batch_size_list[i], dP))
plt.figure()
plt.plot(batch_size_list, correct_rate)
plt.xlabel("batch_size")
plt.ylabel("correct_rate")
plt.show()
结果如图
看起来主要影响力在于梯度下降速度和平滑程度的batch_size在足够大之后并不怎么影响最终结果,所考虑使用20作为batch_size的最终值
- IV.调整max_epoch
代码如下
if __name__ == '__main__':
n_output = 10
dataReader = LoadData(n_output)
n_images = dataReader.num_example
n_input = dataReader.num_feature
dP = InitialParameters3(n_input, 128, 64, n_output, 2)
correct_rate = []
m_epoch_list = [1, 2, 5, 10, 20, 30]
for i in range(5):
correct_rate.append(main(0.3, 128, 64, m_epoch_list[i], 20, dP))
plt.figure()
plt.plot(m_epoch_list, correct_rate)
plt.xlabel("m_epoch")
plt.ylabel("correct_rate")
plt.show()
结果如下
可以看出随着max_epoch值的增大,准确率随之提升,但是准确率提升的幅度却在下降,因此可以认为当max_epoch取得一个值后,之后再提升所带来的准确率提升效益过低,结合本次实验的结果,可以认为max_epoch取值为20时可以在不影响运行速度的情况下取得最佳的结果
3.最终结果显示
根据上述实验结果得出结论,各个参数在达到以下值时,准确率有最佳的结果
learning_rate = 0.3
n_hidden1 = 128
n_hidden2 = 64
m_epoch = 20
batch_size = 20
将这些值带入原代码中运行得到最终的结果
rate=9825 / 10000 = 0.9825
其Loss曲线为