import numpy as np
import sklearn
from sklearn import datasets
from matplotlib import pyplot as plt
class Config:
eta=0.003#学习率
input_dim=2#输入层神经元个数,即样本的特征数,这里是横纵坐标
hidden_dim=3#隐层神经元个数
output_dim=2#输出层神经元个数,分别代表P(y=0)与P(y=1),取较大者为数据点的分类
N=200#训练集样本数
def generate_data():
np.random.seed(0)
X,Y=sklearn.datasets.make_moons(Config.N,noise=0.20)#大小为N的二分类非线性可分数据集
return X,Y
def softmax(z):#输出层softmax函数,输出为yhat。为了数值稳定防止溢出,进行平移。
z-=np.max(z)
return np.exp(z)/np.sum(np.exp(z))
def predict(x,model):
'''
得到预测输出
'''
p=np.dot(x,model['v'])+model['b']#隐层输入
a=np.tanh(p)#隐层输出
z=np.dot(a,model['w'])+model['c']#输出层输入
yhat=softmax(z)#输出层输出(概率)
return np.argmax(yhat,axis=1),yhat#选概率大的作为分类
def CrossEntropyLoss(y,yhat):#单个样本交叉熵损失函数
return -np.sum(y*np.log(yhat))
def totalLoss(X,Y,model):#训练集总损失
Loss=0.0
for i in range(len(X)):
ypred,yhat=predict(X[i],model)
Loss+=CrossEntropyLoss(Y[i],yhat)
return Loss/len(X)
def build_model(X,Y,iters):
'''
在[0,1)区间内随机初始化连接权重与阈值
'''
v=np.random.random((Config.input_dim,Config.hidden_dim))#输入层到隐层的连接权重
w=np.random.random((Config.hidden_dim,Config.output_dim))#隐层到输出层的连接权重
b=np.random.random((1,Config.hidden_dim))#隐层的阈值
c=np.random.random((1,Config.output_dim))#输出层的阈值
model={}
for t in range(iters):
for i in range(len(X)):#一个训练样本就更新一次参数
#forward propagation
p=np.dot(X[i],v)+b#隐层输入
a=np.tanh(p)#隐层输出
z=np.dot(a,w)+c#输出层输入
yhat=softmax(z)#输出层输出(概率)
#back propagation
g=yhat-Y[i]#输出层梯度
w+=-Config.eta*np.dot(a.transpose(),g)#更新隐层到输出层的连接权重
c+=-Config.eta*g#更新输出层的阈值
h=np.dot(g,w.transpose())*(1-np.power(a,2))#隐层梯度
v+=-Config.eta*np.dot(np.array([X[i]]).transpose(),h)#更新输入层到隐层的连接权重
b+=-Config.eta*h#更新隐层的阈值
model={'v': v, 'w': w, 'b': b, 'c': c}
if(t%100==0):
print "after",t,"iteration:",totalLoss(X,Y,model)
return model
def plot_decision_boundary(pred_func,X,Y):
#设置最小最大值, 加上一点外边界
x_min,x_max=X[:,0].min()-.5,X[:,0].max()+.5
y_min,y_max=X[:,1].min()-.5,X[:,1].max()+.5
h=0.01
# 根据最小最大值和一个网格距离生成整个网格
xx,yy=np.meshgrid(np.arange(x_min,x_max,h),np.arange(y_min,y_max,h))
# 对整个网格预测边界值
Z,Yhat=pred_func(np.c_[xx.ravel(),yy.ravel()])
Z=Z.reshape(xx.shape)
# 绘制边界和数据集的点
plt.contourf(xx,yy,Z,cmap=plt.cm.Spectral)
plt.scatter(X[:,0],X[:,1],c=Y,cmap=plt.cm.Spectral)
def NN():
X,Y=generate_data()#产生数据集
model=build_model(X,Y,1500)#建立神经网络模型,iters为迭代次数
plot_decision_boundary(lambda x: predict(x,model),X,Y)
plt.title("Decision Boundary for hidden layer size %d" %Config.hidden_dim)
plt.show()
if __name__ == "__main__":
NN()
求解!!