目录
实验环境
- Python 3.6
- NumPy: 1.14.2
- Matplotlib: 2.2.2
- Pandas: 0.22.0
- scikit-learn: 0.19.1
1.原型感知机概览
2.感知机python代码
# -*- coding: utf-8 -*-
"""
Created on Tue Sep 4 10:25:06 2018
人工神经网络--感知机分类
数据:
http://labfile.oss.aliyuncs.com/courses/1081/course-12-data.csv
"""
"""加载数据集
"""
import pandas as pd
df = pd.read_csv("course-12-data.csv", header=0) # 加载数据集
#print('df',df)#df X0 X1 Y 5.1 3.5 -1
"""感知机随机梯度下降算法实现
"""
def perceptron_sgd(X, Y, alpha, epochs):
"""
参数:
X -- 自变量数据矩阵
Y -- 因变量数据矩阵
alpha -- lamda 参数
epochs -- 迭代次数
返回:
w -- 权重系数
b -- 截距项
"""
w = np.zeros(len(X[0])) # 初始化参数为 0
b = np.zeros(1)
for t in range(epochs): # 迭代
for i, x in enumerate(X):
if ((np.dot(X[i], w)+b)*Y[i]) <= 0: # 判断条件
w = w + alpha*X[i]*Y[i] # 更新参数
b = b + alpha*Y[i]
return w, b
"""感知机求最佳分割线
"""
import numpy as np
X = df[['X0','X1']].values
Y = df['Y'].values
#print('YYYY',Y)
alpha = 0.0005
epochs = 1000#数据总长度
L=perceptron_sgd(X, Y, alpha, epochs)#(array([ 4.93, -6.98]), array([-3.3]))
print(L)#函数为f(x)=4.93∗x1−6.98∗x2−3.3
"""求解分类正确率
"""
w1 = L[0][0]
w2 = L[0][1]
b = L[1]
z = np.dot(X, np.array([w1, w2]).T) + b #f(x)式子
np.sign(z) #感知机公式
from sklearn.metrics import accuracy_score
a=accuracy_score(Y, np.sign(z)) #预测准确率 0.9866666666666667
print(a)
"""绘制决策线
不需要掌握
"""
import matplotlib.pyplot as plt
# 绘制轮廓线图,不需要掌握
plt.figure(figsize=(10, 6))
plt.scatter(df['X0'],df['X1'], c=df['Y'])
x1_min, x1_max = df['X0'].min(), df['X0'].max(),
x2_min, x2_max = df['X1'].min(), df['X1'].max(),
xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max))
grid = np.c_[xx1.ravel(), xx2.ravel()]
probs = (np.dot(grid, np.array([L[0][0], L[0][1]]).T) + L[1]).reshape(xx1.shape)
plt.contour(xx1, xx2, probs, [0], linewidths=1, colors='red');
"""绘制损失函数
计算每次迭代后的损失函数值
"""
def perceptron_loss(X, Y, alpha, epochs):
"""
参数:
X -- 自变量数据矩阵
Y -- 因变量数据矩阵
alpha -- lamda 参数
epochs -- 迭代次数
返回:
loss_list -- 每次迭代损失函数值列表
"""
w = np.zeros(len(X[0])) # 初始化参数为 0
b = np.zeros(1)
loss_list = []
for t in range(epochs): # 迭代
loss_init = 0
for i, x in enumerate(X):
if ((np.dot(X[i], w)+b)*Y[i]) <= 0: # 判断条件
loss_init += (((np.dot(X[i], w)+b)*Y[i]))
w = w + alpha*X[i]*Y[i] # 更新参数
b = b + alpha*Y[i]
loss_list.append(loss_init * -1)
return loss_list
#绘制损失函数图
loss_list = perceptron_loss(X, Y, alpha, epochs)
plt.figure(figsize=(10, 6))
plt.plot([i for i in range(len(loss_list))], loss_list)
plt.xlabel("Learning rate {}, Epochs {}".format(alpha, epochs))
plt.ylabel("Loss function")
运行结果图:
分析:数据集线性可分,却造成损失函数变换曲线震荡的原因一般有两点:学习率太大或者迭代次数太少。
当迭代次数约为 700
次,即上图后半段时,损失函数的值等于 0
3.人工神经网络概览
4.人工神经网络python代码
# -*- coding: utf-8 -*-
"""
Created on Tue Sep 4 19:48:30 2018
神经网络实现分类
数据:course-12-data.csv
http://labfile.oss.aliyuncs.com/courses/1081/course-12-data.csv
"""
# sigmoid 函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# sigmoid 函数求导
def sigmoid_derivative(x):
return sigmoid(x) * (1 - sigmoid(x))
# 示例神经网络完整实现
class NeuralNetwork:
# 初始化参数
def __init__(self, X, y, lr):
self.input_layer = X
self.W1 = np.random.rand(self.input_layer.shape[1], 3)
self.W2 = np.random.rand(3, 1)
self.y = y
self.lr = lr
self.output_layer = np.zeros(self.y.shape)
# 前向传播
def forward(self):
self.hidden_layer = sigmoid(np.dot(self.input_layer, self.W1))
self.output_layer = sigmoid(np.dot(self.hidden_layer, self.W2))
# 反向传播
def backward(self):
d_W2 = np.dot(self.hidden_layer.T, (2 * (self.output_layer - self.y) *
sigmoid_derivative(np.dot(self.hidden_layer, self.W2))))
d_W1 = np.dot(self.input_layer.T, (
np.dot(2 * (self.output_layer - self.y) * sigmoid_derivative(
np.dot(self.hidden_layer, self.W2)), self.W2.T) * sigmoid_derivative(
np.dot(self.input_layer, self.W1))))
# 参数更新
self.W1 -= self.lr * d_W1
self.W2 -= self.lr * d_W2
"""加载数据集
"""
import pandas as pd
df = pd.read_csv("course-12-data.csv", header=0) # 加载数据集
#对数据形状进行调整
X = df[['X0','X1']].values # 输入值
y = df['Y'].values.reshape(len(X), -1) # 真实 y,处理成 [[],...,[]] 形状
"""网络迭代 100 次:
绘制 loss 曲线变化图
"""
import matplotlib.pyplot as plt
nn = NeuralNetwork(X, y, lr=0.001) # 定义模型
loss_list = [] # 存放损失数值变化
for i in range(100):
nn.forward() # 前向传播
nn.backward() # 反向传播
loss = np.sum((y - nn.output_layer) ** 2) # 计算平方损失
loss_list.append(loss)
print("final loss:", loss)
plt.plot(loss_list) # 绘制 loss 曲线变化图
"""
损失函数逐渐减小并接近收敛,变化曲线比感知机计算会平滑很多。
不过,由于我们去掉了截距项,且网络结构太过简单,导致收敛情况并不理想。
"""
运行结果图:损失函数平滑很多
分析:
损失函数逐渐减小并接近收敛,变化曲线比感知机计算会平滑很多。不过,由于我们去掉了截距项,且网络结构太过简单,导致收敛情况并不理想。
5.人工神经网络-sklearn练习
5.1函数
5.2 代码
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 5 16:38:57 2018
训练手写字符识别人工神经网络---sklearn实现
数据:手写字符
sklearn.neural_network.MLPClassifier()
"""
import numpy as np
from sklearn import datasets
digits=datasets.load_digits()
print(digits,'digits.data',digits.data,'digits.target',digits.target,'digits.images',digits.images[0])
from matplotlib import pyplot as plt
image=digits.images
fig,axes=plt.subplots(1,5,figsize=(12,4))
#for i in range(5):
# axes[i].imshow(image[i],cmap=plt.cm.gray_r)
#更好的写法
for i,image in enumerate(digits.images[:5]):
axes[i].imshow(image,cmap=plt.cm.gray_r)
#训练集划分8:2
from sklearn.model_selection import train_test_split
train_x,test_x,train_y,test_y=train_test_split(digits.data,digits.target,test_size=0.2,random_state=30)
#测试
print(len(train_x),len(train_y),len(test_x),len(test_y))
#搭建模型
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score
def mpl():
model=MLPClassifier(hidden_layer_sizes=(100,50),activation='tanh',solver='sgd',learning_rate_init=0.05,learning_rate='constant',max_iter=1000,random_state=1)
model.fit(train_x,train_y)
score=accuracy_score(test_y,model.predict(test_x))
return model,score
print(mpl()[0],mpl()[1])