tensorflow⼊门——BP神经⽹络⾮线性回归最完整过程(含预测)
这是吐槽:
本科⼟⽊,由于各种经验公式的困扰,突发奇想想⽤神经⽹络去训练⾮线性的数据。然后从⽹络上查资料,发现BP神经⽹络对⾮线性数据有良好的处理效果。从百度上copy的⼀句话:其突出优点就是具有很强的⾮线性映射能⼒和柔性的⽹络结构。 总之⽐⼈⼯猜测⽤公式回归会强很多,如果有同学跟我⼀样的情况也可以尝试这种⾮线性回归。对神经⽹络⼊门困难的同学,这个也是⽐mnist⼿写数字识别更为基础的教程。
由于⾮计算机专业,然后⽹上的教程并不是特别详细,有的有过程没有预测的步骤,有的有步骤没有预测⽅法,有的有预测⼜是简单的线性回归(线性回归我为啥不直接⽤最⼩⼆乘法?),⼀路上基本吧能趟的坑都趟完了T_T。所以下⾯就是我的趟坑实录,不。。。。tensorflow⼊门——BP神经⽹络⾮线性回归最完整过程。
1.安装环境
我的安装环境是win10 + Aanacoda(最新版)+python3.6(tf⽬前不兼容3.7)+tensorflow-gpu(最新版)+CUDA9.0+cudnn-9.0-windows10-x64-v7.3.1.20
显卡型号:GTX1050(tf只⽀持N卡,不⽀持A卡)
注:CUDA和cuDNN版本根据⾃⼰显卡选择,如果都不成功⽽且显卡跟我的差不多可以尝试我的搭配,安装Aanacoda还是很有必要的,不会让你的python版本和三⽅库混乱,在安装tensorflow和其他三⽅库时不要⽤Aanacoda的导航栏去安装,它只会安装最低版本(反正这样安装我是启动不了),选择终端打开环境,⽤pip安装最准确(不过需要提前配置好Aanacoda的源),如果以上⽅法都不起作⽤,请使⽤tensorflow—cpu版本吧,只是运算慢⼀点,对没有上万数据的⾮线性回归,训练时间应该是可以忍受的。
刚⼊门的同学也许就常常卡在环境配置这块,不⽤灰⼼,我当初啥也都不懂,对⼊门来说配置环境就是最⼤的⼀道难关,我也卡在这⾥,⼀个下午配置了五六次。上⾯并没有把环境配置说的很详细是因为⽹上资料其实很多,耐⼼去⼀个个试⼀般都可以成功的。
2.⼈⼯神经⽹络介绍
⼈⼯神经⽹络近年⼤⽕,万恶的资本家的炒作给它加上了⼀种⽆所不能的光环。但是从最最基础的来源来说,其实就是我们⼩学学过的
y=kx+b,神经⽹络⾥⼀般是写为y = wx+b。当然神经⽹络是由数个y = wx+b组成再结合⼀些信息论(l
oss函数)概率论,激活函数,等等⼀些数学⽅法。但是它的核⼼还是数个y=wx+b,所以⼈⼯神经⽹络并不是多复杂的东西,咱们⼩学就学过它最核⼼的东西。当然只是说理解和使⽤不会让你构成障碍,但是你要你从y = wx +b推导到神经⽹络甚⾄优化改进还是需要⼤量的知识储备的。
总之,使⽤tf学习框架的门槛并没有很⾼,⼀般上过⼩学有点相关基础的⼤学⽣都可以做到的。
知识背景:
(1)能看懂python代码:除了基础的语句⽤法(⽐如列表字典这些),还包括⼀些常⽤的三⽅库如numpy,matplotlib库等等,其实不懂也可以百度。
(2)数学基础:如矩阵相乘,正态分布(正态分布其实很有意思,运⽓就像⼀个⾃然规律⼀样,却可以⽤公式表达,学会了你可以科学算命,可以⾃⾏百度⼀下)
(3)能看懂我上⾯说的神经⽹络介绍。
好的步⼊正题:
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
导⼊⽤到的模块
learning_rate =0.05 #学习率
num_of_trian =600 #训练的次数
training_display =10 #每训练多少次显⽰
data_path ="data/model"#模型存放路径
⼀些初始参数的设置,⼤家可以尝试修改这些数据,观察对模型训练的影响
#⽣成添加噪⾳数据
x_data = np.linspace(-2,2,400)[:,np.newaxis]
noise = al(0,0.5,x_data.shape)
y_data = np.square(x_data)-0.5+ noise
⽣成带噪⾳的数据
#未添加噪点函数
x= np.linspace(-2,2,400)
y= np.square(x)-0.5
这是原型曲线
#输⼊层
with tf.name_scope("inputs"):
朱丹xs = tf.placeholder(tf.float32,[None,1],name="x_input")
ys = tf.placeholder(tf.float32,[None,1],name="y_input")
这是输⼊层,xs,ys并不是数据,它只是⼀个占位符,就和图书馆占座⼀样,虽然有数,不过没⼈坐,是等着有⼈来坐。
(tf.name_scope()是为了⽅便你在tensorboard⽣成⼀个图)
小学二年级语文下册期末试卷with tf.name_scope('hidden_layer'): #隐藏层。将隐藏层权重、偏置、净输⼊放在⼀起
with tf.name_scope('weight'): #权重
W1= tf.Variable(tf.random_normal([1,10]))#⼀⾏⼗列随机正态分布。即⼗个神经元
tf.summary.histogram('hidden_layer/weight',W1)
with tf.name_scope('bias'): #偏置
b1 = tf.s([1,10]))+0.1
tf.summary.histogram('hidden_layer/bias', b1)
with tf.name_scope('Wx_plus_b'): #净输⼊
Wx_plus_b1 = tf.matmul(xs,W1)+ b1
tf.summary.histogram('hidden_layer/Wx_plus_b',Wx_plus_b1)
output1 = tf.nn.softplus(Wx_plus_b1) #激活函数relu平滑版
这⾥终于出现了我们所学的⼩学知识。w1就是⼩学公式中的k,b1就是b, Wx_plus_b1就是y了。
好听的歌曲排行榜不过这⾥的w1并不是⼀个数,tf.random_normal([1,10]),⽣成了⼀个⼀⾏⼗列随机正态分布的矩阵,意思就是w1是⼀个由10个正态分布的w组成的矩阵。对应的tf.zeros([1,10])⽣成了⼀个⼀⾏⼗列的0矩阵,就是b1是⼀个由10个0组成的矩阵,加的0.1其实是初始的b,最佳的位置就是⼀条直线穿过所有的点,正好把所有的点分成两部分,线上⽅的点正好等于线下⾯的点的数量。不没到最佳位置也⽆所谓,⼤概的位置,对训练影响不⼤。
tf.matmul(xs,W1) 就是对应的元素相乘,不是矩阵相乘。
到这⾥就是完整的y = wx+b公式,再加上激活函数(⼤家也可以查资料,激活函数并不复杂,⽹上 资料很多,这⾥不多介绍)。这也就是隐藏层的结构。
with tf.name_scope('output_layer'): #输出层。将输出层权重、偏置、净输⼊放在⼀起
小学生自我评价25字with tf.name_scope('weight'): #权重
W2= tf.Variable(tf.random_normal([10,1]))
tf.summary.histogram('output_layer/weight',W2)
with tf.name_scope('bias'): #偏置
b2 = tf.s([1,1]))+0.1
tf.summary.histogram('output_layer/bias', b2)
with tf.name_scope('Wx_plus_b'): #净输⼊
Wx_plus_b2 = tf.matmul(output1,W2)+ b2
tf.summary.histogram('output_layer/Wx_plus_b',Wx_plus_b2)
output2 = Wx_plus_b2
这个是输出层,⼤同⼩异,不过输出层⼀般没有激活函数。
#损失
with tf.name_scope("loss"):
loss = tf.reduce_duce_sum(tf.square(ys - output2),reduction_indices=[1]))
tf.summary.scalar("loss",loss)
损失函数,这个不明⽩也没有关系,其实就是求⽅差。。和最⼩⼆乘法有点像
深圳旅游景区笔记本电脑电源功率with tf.name_scope("train"):
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
#合并数据
merged = _all()
GradientDescentOptimizer就是梯度下降的英语。梯度下降,可以理解为使导数差下降的,多维矩阵版,minimize就是要使loss最⼩。好了到此为⽌,神经⽹络已经搭建完毕。结构⾮常简单,输⼊-隐藏-输出,再加上设置loss函数,设置梯度下降⽅法。
可能现在还有点蒙,还是不太理解为啥y = wx + b可以组成神经⽹络。那是因为还没有数据输⼊,整个⽹络还是空的,还没有进⾏变化。就是那个占座的⼈还没坐下来,你肯定会觉得这⼈没素质,等你看到他上完厕所坐下来,才会知道他还掏出了⼿机在图书馆打游戏刷微博。
#设置绘图器
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('训练过程')
ax.scatter(x_data,y_data,s=5,label ="训练数据")
plt.plot(x,y,c ="red",label ="曲线原型")
plt.show(block = False)
设置matplot绘图器
with tf.Session()as sess:
#初始化
init = tf.global_variables_initializer()
sess.run(init)
#读取原有模型继续训练
#saver = tf.train.Sav er()
#store(sess,"data/model")
#写⼊训练数据到logs⽂件夹下
writer = tf.summary.FileWriter("logs",aph)
开启会话,初始化,做好准备⼯作。
for train in range(num_of_trian):
sess.run(train_step,feed_dict={xs:x_data,ys:y_data})
prediction_value = sess.run(output2, feed_dict={xs: x_data})
lines = ax.plot(x_data, prediction_value, c ="blue", lw=5,label ="预测曲线")#绘制训练过程
plt.legend()#显⽰标题元素
plt.pause(0.1)
if train % training_display ==0:
result = sess.run(merged,feed_dict={xs:x_data,ys:y_data})
writer.add_summary(result,train)
print(train,sess.run(loss,feed_dict={xs:x_data,ys:y_data}))
plt.savefig("picture\\"+str(train)+".png")#保存训练图⽚
try:
ve(lines[0])
except Exception:
pass
saver = tf.train.Saver()
saver.save(sess,data_path)#储存模型
这⾥就开始喂⼊数据了,通过sess.run()可以将数据在整个神经⽹络上跑。
⼀开始xs数据先进⼊,通过y = wx +b 求出来y,ys数据再进去和算出来的y(即output)对⽐,他会告诉神经⽹络调整w,b,就好像xs位置上的⼈在打游戏,旁边ys位置上的⼈看到了说:“⼩⽼弟,你的技术(w)和⼿机配置(b)不⾏哦。”,xs位置上的⼩⽼弟听了觉得有道理,调整技术(w)提升了⼿机配置(b),这样就完成了⼀次训练过程。
第⼆次训练,还是xs位置上的⼈开始打游戏,ys上的⼈看了⼜说:“⼿机配置(b)可以了,技术还是要提升⼀点(w)。”,⼩⽼弟听了觉得有道理,不换⼿机(b)开始提升技术(w)。
当然,⼀般不会出现第⼆轮训练b就不变了,xs的⽔平取决与ys的⽔平。如果ys只是黄⾦,那么xs听取了千百次ys的建议。则xs的技术和⼿机配置就会越来越像ys
则他的⽔平就越来越像ys。
训练过程不难理解,可是为啥要10个w和b?就在于,我们回归的是⾮线性模型。在我们的隐藏层中有10个神经元,⼀个神经元对应⼀个w,b。每个神经元相当于记录了要学习的曲线⼀个特征。
这是⼀个不恰当的例⼦,神经元的数字特征更为抽象,不过我们也可以知道,神经元越多,特征越多。同样的⽹络层数越多,收集的特征也越多。模型拟合的情况会越好,不过,它们的数量应当在⼀个合适的范围,否则会浪费计算资源。
#⽤于预测模型上任意⼀点
flag = True
with tf.Session()as sess2:
sess2.run(init)
saver = tf.train.Saver()
while flag:
b =input("请输⼊读取的X值:")
if b =="exit":
flag = False
else:
a =eval("np.array([["+b+"]])")
print("x={},y={}".format(a[0][0], sess2.run(output2, feed_dict={xs:a})[0][0]))
最后⼀步,预测!终于,千百次训练下,xs上的⼩⽼弟觉得,他对ys的技术(w)和⼿机配置(b)都了然于⼼并且记在了⼩本本
feed_dict{}上,不过这时feed_dict{}并不是⽤来储存,⽽是⽤来索引,根据xs对应的元素,到对应的w和b,⽤sess2.run()把xs上的值(由你给出)从神经⽹络再跑⼀次。进⾏诸如xw + b的计算,得到结果。就完成了⼀次预测。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论