# [Python人工智能] 二.theano实现回归神经网络分析

"莫烦大神" 网易云视频地址：http://study.163.com/provider/1111519/course.html

## 一. 定义神经网络Layer类

L1 = Layer(inputs, in_size=1, out_size=10, activation_function)
参数包括输入值，输入节点数，输出节点数和激励函数
L2 = Layer(L1.outputs, 10, 1, None)
参数中L1的输出作为输入值，L1的输出10个节点作为输入节点，输出节点1个，激励函数为None。

class Layer(object):
def __init__(self, inputs, in_size, out_size, activation_function=None):
#权重: 平均值为0 方差为1 行数为in_size  列数为out_size
self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
#bias
self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
#乘法加bias
self.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法
#激励函数
self.activation_function = activation_function

#默认为None,否则进行激活
if activation_function is None:
self.outputs = self.Wx_plus_b
else:
self.outputs = self.activation_function(self.Wx_plus_b)


## 二. 回归神经网络实现

1.制造虚拟数据

#coding:utf-8
import numpy as np
import theano.tensor as T
import theano
from theano import function

class Layer(object):
def __init__(self, inputs, in_size, out_size, activation_function=None):
#权重: 平均值为0 方差为1 行数为in_size  列数为out_size
self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
#bias
self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
#乘法加bias
self.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法
#激励函数
self.activation_function = activation_function

#默认为None,否则进行激活
if activation_function is None:
self.outputs = self.Wx_plus_b
else:
self.outputs = self.activation_function(self.Wx_plus_b)

#回归神经网络 Regression

#1.制造虚拟数据
import matplotlib.pyplot as plt
#Make up some fake data
x_data = np.linspace(-1,1,300)[:, np.newaxis] #300个点进行训练
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise   #y = x^2 - 0.5
#一元二次散点图
plt.scatter(x_data, y_data)
plt.show()

2.增加神经层

L1 = Layer(x, 1, 10, T.nnet.relu)
输入为x，1维的data，神经元10个，relu非线性激励函数
L2 = Layer(L1.outputs, 10, 1, None)
输入为L1输出值， L2的in_size为L1的神经元10，假设L2输出为最终output

#coding:utf-8
import numpy as np
import theano.tensor as T
import theano
from theano import function

class Layer(object):
def __init__(self, inputs, in_size, out_size, activation_function=None):
#权重: 平均值为0 方差为1 行数为in_size  列数为out_size
self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
#bias
self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
#乘法加bias
self.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法
#激励函数
self.activation_function = activation_function

#默认为None,否则进行激活
if activation_function is None:
self.outputs = self.Wx_plus_b
else:
self.outputs = self.activation_function(self.Wx_plus_b)

#回归神经网络 Regression

#1.制造虚拟数据
import matplotlib.pyplot as plt
#Make up some fake data
x_data = np.linspace(-1,1,300)[:, np.newaxis] #300个点进行训练
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise   #y = x^2 - 0.5
#一元二次散点图
plt.scatter(x_data, y_data)
plt.show()

#2.定义输入和神经元
#determine the inputs dytpe
x = T.dmatrix('x')  #d代表64位float类型
y = T.dmatrix('y')
L1 = Layer(x, 1, 10, T.nnet.relu)
L2 = Layer(L1.outputs, 10, 1, None)

3.计算误差与梯度下降更新

L1.W, L1.W-learnging_rate*gW1：
(原始的权重-学习效率*下降幅度)并且更新为L1.W，通过该方法将L1.W、L1.b、L2.W、L2.b更新。

#coding:utf-8
import numpy as np
import theano.tensor as T
import theano
from theano import function

class Layer(object):
def __init__(self, inputs, in_size, out_size, activation_function=None):
#权重: 平均值为0 方差为1 行数为in_size  列数为out_size
self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
#bias
self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
#乘法加bias
self.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法
#激励函数
self.activation_function = activation_function

#默认为None,否则进行激活
if activation_function is None:
self.outputs = self.Wx_plus_b
else:
self.outputs = self.activation_function(self.Wx_plus_b)

#回归神经网络 Regression

#1.制造虚拟数据
import matplotlib.pyplot as plt
#Make up some fake data
x_data = np.linspace(-1,1,300)[:, np.newaxis] #300个点进行训练
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise   #y = x^2 - 0.5
#一元二次散点图
plt.scatter(x_data, y_data)
plt.show()

#2.定义输入和神经元
#determine the inputs dytpe
x = T.dmatrix('x')  #d代表64位float类型
y = T.dmatrix('y')
L1 = Layer(x, 1, 10, T.nnet.relu)
L2 = Layer(L1.outputs, 10, 1, None)

#3.计算误差与梯度下降更新
#误差为预测值与真实值差别
cost = T.mean(T.square(L2.outputs - y)) #mean()求平均误差
#梯度下降，让预测值更接近真实值，误差越大，降低趋势越大
gW1, gb1, gW2, gb2 = T.grad(cost, [L1.W, L1.b, L2.W, L2.b]) #权重和bias
#学习效率: 神经网络中learning_rate通常小于1的数字,0.05保证神经网络学习比较精细
learning_rate = 0.05

#更新四个神经网络的参数
train = theano.function(
inputs = [x,y],
outputs = cost,
(L1.b, L1.b-learning_rate*gb1),
(L2.W, L2.W-learning_rate*gW2),
(L2.b, L2.b-learning_rate*gb2)
]
)
#(L1.W, L1.W-learnging_rate*gW1)
#(原始的权重-学习的效率*下降的幅度)更新为L1.W

4.预测结果

#coding:utf-8
import numpy as np
import theano.tensor as T
import theano
from theano import function

class Layer(object):
def __init__(self, inputs, in_size, out_size, activation_function=None):
#权重: 平均值为0 方差为1 行数为in_size  列数为out_size
self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
#bias
self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
#乘法加bias
self.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法
#激励函数
self.activation_function = activation_function

#默认为None,否则进行激活
if activation_function is None:
self.outputs = self.Wx_plus_b
else:
self.outputs = self.activation_function(self.Wx_plus_b)

#回归神经网络 Regression

#1.制造虚拟数据
import matplotlib.pyplot as plt
#Make up some fake data
x_data = np.linspace(-1,1,300)[:, np.newaxis] #300个点进行训练
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise   #y = x^2 - 0.5
#一元二次散点图
plt.scatter(x_data, y_data)
plt.show()

#2.定义输入和神经元
#determine the inputs dytpe
x = T.dmatrix('x')  #d代表64位float类型
y = T.dmatrix('y')
L1 = Layer(x, 1, 10, T.nnet.relu)
L2 = Layer(L1.outputs, 10, 1, None)

#3.计算误差与梯度下降更新
#误差为预测值与真实值差别
cost = T.mean(T.square(L2.outputs - y)) #mean()求平均误差
#梯度下降，让预测值更接近真实值，误差越大，降低趋势越大
gW1, gb1, gW2, gb2 = T.grad(cost, [L1.W, L1.b, L2.W, L2.b]) #权重和bias
#学习效率: 神经网络中learning_rate通常小于1的数字,0.05保证神经网络学习比较精细
learning_rate = 0.05

#更新四个神经网络的参数
train = theano.function(
inputs = [x,y],
outputs = cost,
(L1.b, L1.b-learning_rate*gb1),
(L2.W, L2.W-learning_rate*gW2),
(L2.b, L2.b-learning_rate*gb2)
]
)
#(L1.W, L1.W-learnging_rate*gW1)
#(原始的权重-学习的效率*下降的幅度)更新为L1.W

#4.预测结果
#训练时会给y求cost, 而预测输入只给出x用来做预测
predict = theano.function(inputs=[x],  outputs=L2.outputs)

for i in range(1000):
#training 把x_data和y_data放到函数x、y中
err = train(x_data, y_data) #误差

#每隔50步输出err, 如果err不断减小说明神经网络在学到东西, 因为预测值与真实值误差在不断减小
if i % 50 == 0:
print(err)

2.079139917311914
0.019342171772016286
0.010080951605219858
0.007202397774306516
0.005702041299886045
0.004946926023254156
0.004565940080184372
0.0043433009094413985
0.00421325480276665
0.0041214880336559725
0.004046461715568916
0.003989685842213987
0.003934933552824453
0.003886586291155118
0.003843283475886867
0.0038068442317786316
0.0037721487639369986
0.0037432478192238835
0.003712756532212612
0.00368813308403329

## 三. 回归神经网络可视化

#coding:utf-8
import numpy as np
import theano.tensor as T
import theano
from theano import function

class Layer(object):
def __init__(self, inputs, in_size, out_size, activation_function=None):
#权重: 平均值为0 方差为1 行数为in_size  列数为out_size
self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
#bias
self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
#乘法加bias
self.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法
#激励函数
self.activation_function = activation_function

#默认为None,否则进行激活
if activation_function is None:
self.outputs = self.Wx_plus_b
else:
self.outputs = self.activation_function(self.Wx_plus_b)

#回归神经网络 Regression

#1.制造虚拟数据
import matplotlib.pyplot as plt
#Make up some fake data
x_data = np.linspace(-1,1,300)[:, np.newaxis] #300个点进行训练
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise   #y = x^2 - 0.5
#一元二次散点图
plt.scatter(x_data, y_data)
plt.show()

#2.定义输入和神经元
#determine the inputs dytpe
x = T.dmatrix('x')  #d代表64位float类型
y = T.dmatrix('y')
L1 = Layer(x, 1, 10, T.nnet.relu)
L2 = Layer(L1.outputs, 10, 1, None)

#3.计算误差与梯度下降更新
#误差为预测值与真实值差别
cost = T.mean(T.square(L2.outputs - y)) #mean()求平均误差
#梯度下降，让预测值更接近真实值，误差越大，降低趋势越大
gW1, gb1, gW2, gb2 = T.grad(cost, [L1.W, L1.b, L2.W, L2.b]) #权重和bias
#学习效率: 神经网络中learning_rate通常小于1的数字,0.05保证神经网络学习比较精细
learning_rate = 0.05

#更新四个神经网络的参数
train = theano.function(
inputs = [x,y],
outputs = cost,
(L1.b, L1.b-learning_rate*gb1),
(L2.W, L2.W-learning_rate*gW2),
(L2.b, L2.b-learning_rate*gb2)
]
)
#(L1.W, L1.W-learnging_rate*gW1)
#(原始的权重-学习的效率*下降的幅度)更新为L1.W

#4.预测结果
#训练时会给y求cost, 而预测输入只给出x用来做预测
predict = theano.function(inputs=[x],  outputs=L2.outputs)

#可视化分析

#plot the fake data
fig = plt.figure()
ax.scatter(x_data,y_data) #散点图效果

#输入红线并且连续不断更新
plt.ion()
plt.show() #参数block=True: 只显示这张图,关掉图后才运行后面程序

#每隔50步输出err并绘制拟合曲线
#cost值不断减小说明预测值与真实值误差在不断减小,拟合直线越来越接近
for i in range(1000):
#误差: training 把x_data和y_data放到函数x、y中
err = train(x_data, y_data)
pre = predict(x_data)

#to visualize the result and improvement
#查看神经网络结果和拟合提升过程
if i % 50 == 0:

#消除红线, 否则每次的红线绘制在一起
#因为第一步没有红线, 故使用try忽略第一步
try:
ax.lines.remove(lines[0])
except Exception:
pass

predicted_value = predict(x_data)
#plot the prediction
lines = ax.plot(x_data, predicted_value, 'r-', lw=5) #x和预测y lw线宽度
plt.pause(1) #暂定1秒

#输出误差
print(err)
#print(pre)

(By:Eastmount 2018-05-21 下午4点
http://blog.csdn.net/eastmount/ )