首先分析鸢尾花该如何分类:
分析后我们知道将4个特征作为输入层,3个种类作为输出层,中间有一个作为桥梁的隐藏层(随便设的12个神经元)。
首先先读取数据:
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
hua = datasets.load_iris()
x = hua.data #特征值
y = hua.target #目标值
然后要对数据进行归一化处理:
x = (x - 0.1)/(7.9 - 0.1) #归一化
因为如果不进行归一化的话会梯度爆炸。
最小-最大归一化是将数据线性映射到[0,1]的范围内。具体计算公式如下:
X' = (X - X_min) / (X_max - X_min)
然后定义sigmoid函数:将回归变为二分类。
def sigmoid(x):
return 1/(1 + np.exp(-x))
sigmoid函数的作用:
比如预测一个学生的成绩(0-100)得到的是一个数85,就是回归。
而得到这个学生是个好学生(成绩大于75)还是坏学生,就是预测。
所以将输入映射到【0,1】区间,得到一个预测值,再将该值映射到sigmoid中,完成了由值到概率之间的转换,也就是分类任务。
多分类任务可以使用多次二分类。
然后自带的函数划分训练集和测试集:
x_train, x_test, y_train, y_test = train_test_split(x,y)
然后设置权重w1,w2以及学习率:
w1 = np.random.normal(0.0, 1, (4, 12))
w2 = np.random.normal(0.0, 1, (12, 3))
xue = 0.01 #学习率设为0.01
因为输入层设置的是112行4列(划分了112个训练集,4列是4个特征),然后隐藏层就应为112*12的矩阵(12个神经元),所以w1因该为4*12的矩阵,又因为输出层为112*3,故w2设为12*3的矩阵。
接下来就应该构建神经网络:
for i in range(300):
out1 = np.dot(x_train, w1)
a1 = sigmoid(out1)
out2 = np.dot(a1, w2)
a2 = sigmoid(out2) #前向预测完成
erro = a2 - y_true #最后的误差
w2f = np.dot(a1.T, erro * a2 * (1-a2)) #求w2斜率(反向传播w2)
qerro = np.dot(erro, w2.T) #隐藏层的误差
w1f = np.dot(x_train.T, qerro * a1 * (1-a1)) #求w1斜率(反向传播w1)
w2 -= w2f * xue
w1 -= w1f * xue
o1 = np.dot(x_test, w1)
a11 = sigmoid(o1)
o2 = np.dot(a11, w2)
a22 = sigmoid(o2)
要理解这个神经网络,首先要知道梯度下降法和反向传播法。
梯度下降法:可以看作是对一个一次函数进行预测,我们首先设置随机的直线,要无限逼近真实的直线,要么就是要不断微调随机直线的斜率,即y=wx+b, 我们要求出w,也就是求斜率,求斜率那么就要求导。
反向传播算法:
其中w1f和w2f为反向传播,推导过程如下:
最后经过300次循环,o1,a11,o2,a22为测试集的
最后将y_train转为矩阵,因为之前的都为矩阵,要进行对比必须全为矩阵
以及将最后的输出处理一下,因为a22为一个2维矩阵,要和0,1,2进行对比
zhuan = np.identity(3)
y_true = zhuan[y_train]
rs = []
for i in range(a22.shape[0]):
rs.append(np.argmax(a22[i]))
rs = np.array(rs)
再定义一个求准确度的函数
def accuse(y_true, y_predict):
return sum(y_true == y_predict) / len(y_true) #函数返回的是预测正确的比例,即预测值等于真实值的数量除以真实值的总数。
最终求准确度:
accuse(y_test, rs)
最终得到结果:准确度为0.97