菜鸟之路——机器学习之BP神经网络个人理解及Python实现
2021-07-16 04:05
标签:matrix pen ase 测试的 count 理论 RoCE [1] 次数 关键词: 输入层(Input layer)。隐藏层(Hidden layer)。输出层(Output layer) 理论上如果有足够多的隐藏层和足够大的训练集,神经网络可以模拟出任何方程。隐藏层多的时候就是深度学习啦 没有明确的规则来设计最好有多少个隐藏层,可以根据实验测试的误差以及准确度来实验测试并改进。 交叉验证方法(cross -validation):把样本分为K份,取一份为测试集,其他为训练集。共取K次,然后取其平均值 BP的步骤 1、初始化权重(weight)以及偏向(bias),随机初始化在[-1.1]之间或[-0.5,0.5之间,每个神经元有一个偏向] 2、对每个特征向量进行Ij=∑wijOi+θj。Oj=1/(1+e-Ij)。(激活函数) 对于输出层:Errj=Oj(1-Oj)(Tj-Oj)。Tj:真实值,Oj:预测值。 对于隐藏层:Errj=Oj(1-Oj)ΣErrkwjk 权重更新:Δwij=(l)ErrjOj。(l)是学习速率一般取[0,1] 偏向更新:Δθj=(l)Errj 3、终止条件 权重的更新低于某个阈值 预测的错误率低于某个阈值 达到预设的一定的循环次数 激活函数一般为以下两个 1,双曲函数:tanhx=(ex-e-x)/(ex+e-x)其一阶导数为1-tanh2x 2,逻辑函数:f(x)=1/(1+e-x) 其一阶导数为f(x)(1-f(x)) 下面是代码 这是写了一个BP神经网络的对象。 其中有一个地方,编写的时候我一直不懂,后来研究了一下 第 30 self.weight.append((2 * np.random.random((layers[i - 1] +1, layers[i] +1)) - 1) * 0.25) 31 self.weight.append((2 * np.random.random((layers[i] +1, layers[i + 1])) - 1) * 0.25) 37 temp=np.ones([X.shape[0],X.shape[1]+1]) #shape返回矩阵的行数与列数。对bias偏向定义初值 38 temp[:,0:-1]=X 39 X=temp 然后就可以写代码进行训练了 运行结果为 X: [[0 0] 然后又写了一个手写数字识别的程序 运行结果 start fitting [[32 0 2 4 1 0 0 0 1 0] [ 1 17 31 2 0 0 0 0 2 0] [ 0 0 55 0 0 0 0 0 0 0] [ 0 0 8 42 0 0 0 0 0 0] [ 0 1 1 0 32 0 0 0 2 0] [ 1 7 9 21 1 1 0 0 1 0] [ 0 0 6 0 12 0 18 0 8 0] [ 1 2 36 3 1 0 0 8 0 0] [ 0 0 14 2 0 0 0 0 18 1] [ 9 2 4 11 0 0 0 1 6 12]] precision recall f1-score support 0 0.73 0.80 0.76 40 1 0.59 0.32 0.41 53 2 0.33 1.00 0.50 55 3 0.49 0.84 0.62 50 4 0.68 0.89 0.77 36 5 1.00 0.02 0.05 41 6 1.00 0.41 0.58 44 7 0.89 0.16 0.27 51 8 0.47 0.51 0.49 35 9 0.92 0.27 0.41 45 avg / total 0.70 0.52 0.48 450 大家注意到,第十四行,教程里面选用的“logistic”激活函数,但是如果用“logistic”得出来的结果为 start fitting C:\Users\admin\PycharmProjects\BP\main.py:10: RuntimeWarning: overflow encountered in exp return 1/(1+np.exp(x)) D:\Anaconda3\lib\site-packages\sklearn\metrics\classification.py:1135: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. ‘precision‘, ‘predicted‘, average, warn_for) [[51 0 0 0 0 0 0 0 0 0] [53 0 0 0 0 0 0 0 0 0] [48 0 0 0 0 0 0 0 0 0] [52 0 0 0 0 0 0 0 0 0] [35 0 0 0 0 0 0 0 0 0] [54 0 0 0 0 0 0 0 0 0] [42 0 0 0 0 0 0 0 0 0] [40 0 0 0 0 0 0 0 0 0] [34 0 0 0 0 0 0 0 0 0] [41 0 0 0 0 0 0 0 0 0]] precision recall f1-score support 0 0.11 1.00 0.20 51 1 0.00 0.00 0.00 53 2 0.00 0.00 0.00 48 3 0.00 0.00 0.00 52 4 0.00 0.00 0.00 35 5 0.00 0.00 0.00 54 6 0.00 0.00 0.00 42 7 0.00 0.00 0.00 40 8 0.00 0.00 0.00 34 9 0.00 0.00 0.00 41 avg / total 0.01 0.11 0.02 450 这个结果严重错误,上一篇我说过怎么看这个矩阵。 我找出来这个的原因在于激活函数,如果用“logistic”,预测出来的Y全部为【0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5】然后经过np.argmax(o)就变成了0。也就解释了为什么矩阵中所有的数字都在第一列。 但我把激活函数换成“tanhx”就没问题了。我也不知道为啥。 看来选激活函数也是一门学问。 到今天,监督学习的分类问题大致学完了,很浅,只是入门,接下来学回归,等把机器学习入门完了,就往深了学。 nn=NeuralNetwork([64,100,10]) 菜鸟之路——机器学习之BP神经网络个人理解及Python实现 标签:matrix pen ase 测试的 count 理论 RoCE [1] 次数 原文地址:https://www.cnblogs.com/albert-yzp/p/9534891.html 1 import numpy as np
2
3 def tanh(x):
4 return np.tanh(x)
5
6 def tanh_derivative(x):
7 return 1.0-np.tanh(x)*np.tanh(x)#tanh(x)的一阶导数
8
9 def logistic(x):
10 return 1/(1+np.exp(x))
11
12 def logistic_derivative(x):
13 return logistic(x)*(1-logistic(x))
14
15
16 class NeuralNetwork: #面向对象编程
17 def __init__(self,layers,activation=‘tanh‘):#构造函数
18 #layers,一个list,神经网络的层数以及每层神经元的个数,有几个数字就是有几层,每个数字就是每层的神经元的个数
19 #activation:用户定义用哪个激活函数。默认为tanh
20 if activation==‘logistic‘:
21 self.activation=logistic
22 self.activation_deriv=logistic_derivative
23 elif activation==‘tanh‘:
24 self.activation=tanh
25 self.activation_deriv=tanh_derivative
26 self.weight=[]
27 for i in range(1,len(layers)-1):
28 #print(layers[i - 1] + 1, layers[i] + 1)
29 #print(layers[i] + 1, layers[i + 1] + 1)
30 self.weight.append((2 * np.random.random((layers[i - 1] +1, layers[i] +1)) - 1) * 0.25)
31 self.weight.append((2 * np.random.random((layers[i] +1, layers[i + 1])) - 1) * 0.25)
32
33 #print("weight:", self.weight)
34
35 def fit(self,X,Y,learning_rate=0.2,epochs=10000):#数据集,目标标记,学习速率,最大学习次数 #神经网络是在抽样去训练。从数据集里随便抽一个去训练。
36 X=np.atleast_2d(X)#确认数据集至少是二维的。
37 temp=np.ones([X.shape[0],X.shape[1]+1]) #shape返回矩阵的行数与列数。对bias偏向定义初值
38 temp[:,0:-1]=X
39 X=temp
40 #print("X_:",X)
41 Y=np.array(Y)
42 #print("Y_:", Y)
43 for k in range(epochs):
44 i=np.random.randint(X.shape[0])
45 a=[X[i]]#随机抽取一个实例
46 #print("a_:", a)
47 for l in range(len(self.weight)):
48 a.append(self.activation(np.dot(a[l],self.weight[l])))#矩阵相乘然后代入激活函数
49 #print("l,a[l],weight[l]:",l, a[l],self.weight[l])
50 #print(‘a__‘,a)
51 #print("error:", l, Y[i], a[-1])
52 error =Y[i]-a[-1]
53 deltas =[error * self.activation_deriv(a[-1])]
54
55 for l in range(len(a)-2,0,-1):
56 deltas.append(deltas[-1].dot(self.weight[l].T)*self.activation_deriv(a[l])) #算每一层的权重变化量
57 deltas.reverse()#翻转一下
58 for i in range(len(self.weight)):
59 layer = np.atleast_2d([a[i]])
60 delta = np.atleast_2d([deltas[i]])
61 self.weight[i]+=learning_rate*layer.T.dot(delta) #.T就是对矩阵的转置
62
63 def prdict(self,x):
64 x=np.array(x)
65 temp = np.ones(x.shape[0]+1)
66 temp[0:-1]=x
67 a=temp
68 for l in range(0,len(self.weight)):
69 a=self.activation(np.dot(a,self.weight[l]))
70 return a
71
这里把特征向量为什么要加一列1。经过我的研究发现加上一列1,为了防止特征值全为0,而标记却不为零的情况。因为全为0的矩阵乘以任何权向量都是0.会导致训练不成功 1 from main import NeuralNetwork#导入刚才写的对象
2 import numpy as np
3
4 nn=NeuralNetwork([2,2,1],‘tanh‘)
5
6 X = np.array([[0,0],[0,1],[1,0],[1,1]])
7 print("X:",X)
8 Y = np.array([1,0,0,1]) #也就是或运算嘛
9 print("Y:",Y)
10 nn.fit(X,Y)
11 #print("nn:",nn)
12 for i in [[0,0],[0,1],[1,0],[1,1]]:
13 print(i,nn.prdict(i))
[0 1]
[1 0]
[1 1]]
Y: [1 0 0 1]
[0, 0] [0.99875886]
[0, 1] [0.00025754]
[1, 0] [1.91186633e-05]
[1, 1] [0.99868908] 1 import numpy as np
2 from sklearn.datasets import load_digits
3 from sklearn.metrics import confusion_matrix,classification_report #对结果的衡量
4 from sklearn.preprocessing import LabelBinarizer #将[0,9]转化为如果是为1,不是就为0的样子
5 from main import NeuralNetwork
6 from sklearn.model_selection import train_test_split #划分训练集与测试集
7
8 digits=load_digits()
9 X=digits.data
10 Y=digits.target
11 X-=X.min()
12 X/=X.max()
13
14 nn=NeuralNetwork([64,100,10])
15 X_train,X_test,Y_train,Y_test=train_test_split(X,Y)
16 labels_train = LabelBinarizer().fit_transform(Y_train)
17 labels_test = LabelBinarizer().fit_transform(Y_test)
18 print("start fitting")
19 nn.fit(X_train,labels_train,epochs=3000)
20 prdictions=[]
21 for i in range(X_test.shape[0]):
22 #print(X_test[i])
23 o=nn.prdict(X_test[i])
24 prdictions.append(np.argmax(o)) #最大的概率对应的那个数
25 #print(Y_test,prdictions)
26 print(confusion_matrix(Y_test,prdictions))
27 print(classification_report(Y_test,prdictions))
import numpy as np
from sklearn.datasets import load_digits
from sklearn.metrics import confusion_matrix,classification_report #对结果的衡量
from sklearn.preprocessing import LabelBinarizer #将[0,9]转化为如果是为1,不是就为0的样子
from main import NeuralNetwork
from sklearn.model_selection import train_test_split #划分训练集与测试集
digits=load_digits()
X=digits.data
Y=digits.target
X-=X.min()
X/=X.max()
X_train,X_test,Y_train,Y_test=train_test_split(X,Y)
labels_train = LabelBinarizer().fit_transform(Y_train)
labels_test = LabelBinarizer().fit_transform(Y_test)
print("start fitting")
nn.fit(X_train,labels_train,epochs=3000)
prdictions=[]
for i in range(X_test.shape[0]):
#print(X_test[i])
o=nn.prdict(X_test[i])
prdictions.append(np.argmax(o)) #最大的概率对应的那个数
#print(Y_test,prdictions)
print(confusion_matrix(Y_test,prdictions))
print(classification_report(Y_test,prdictions))
文章标题:菜鸟之路——机器学习之BP神经网络个人理解及Python实现
文章链接:http://soscw.com/essay/105869.html