机器学习入门之菜鸟之路——机器学习之BP神经网络个人理解及Python实现
小标 2018-09-21 来源 : 阅读 1947 评论 0

摘要:本文主要向大家介绍了机器学习入门之菜鸟之路——机器学习之BP神经网络个人理解及Python实现,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。

本文主要向大家介绍了机器学习入门之菜鸟之路——机器学习之BP神经网络个人理解及Python实现,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。


理论上如果有足够多的隐藏层和足够大的训练集,神经网络可以模拟出任何方程。隐藏层多的时候就是深度学习啦
没有明确的规则来设计最好有多少个隐藏层,可以根据实验测试的误差以及准确度来实验测试并改进。
交叉验证方法(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))
下面是代码

 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 

 
    这是写了一个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这里把特征向量为什么要加一列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))

 
运行结果为
X: [[0 0] [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))

 
 
 
运行结果
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”就没问题了。我也不知道为啥。
看来选激活函数也是一门学问。
   到今天,监督学习的分类问题大致学完了,很浅,只是入门,接下来学回归,等把机器学习入门完了,就往深了学。
 
 
import numpy as npfrom sklearn.datasets import load_digitsfrom sklearn.metrics import confusion_matrix,classification_report #对结果的衡量from sklearn.preprocessing import LabelBinarizer                   #将[0,9]转化为如果是为1,不是就为0的样子from main import NeuralNetworkfrom sklearn.model_selection import train_test_split               #划分训练集与测试集digits=load_digits()X=digits.dataY=digits.targetX-=X.min()X/=X.max()nn=NeuralNetwork([64,100,10])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)) 

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标人工智能机器学习频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程