关键词:

输入层(Input layer)。隐藏层(Hidden layer)。输出层(Output layer)

理论上如果有足够多的隐藏层和足够大的训练集,神经网络可以模拟出任何方程。隐藏层多的时候就是深度学习啦

没有明确的规则来设计最好有多少个隐藏层,可以根据实验测试的误差以及准确度来实验测试并改进。

交叉验证方法(cross -validation):把样本分为K份,取一份为测试集,其他为训练集。共取K次,然后取其平均值

BP的步骤

1、初始化权重(weight)以及偏向(bias),随机初始化在[-1.1]之间或[-0.5,0.5之间,每个神经元有一个偏向]

2、对每个特征向量进行Ij=∑wijOij。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))

下面是代码

 import numpy as np

 def tanh(x):
return np.tanh(x) def tanh_derivative(x):
return 1.0-np.tanh(x)*np.tanh(x)#tanh(x)的一阶导数 def logistic(x):
return 1/(1+np.exp(x)) def logistic_derivative(x):
return logistic(x)*(1-logistic(x)) class NeuralNetwork: #面向对象编程
def __init__(self,layers,activation='tanh'):#构造函数
#layers,一个list,神经网络的层数以及每层神经元的个数,有几个数字就是有几层,每个数字就是每层的神经元的个数
#activation:用户定义用哪个激活函数。默认为tanh
if activation=='logistic':
self.activation=logistic
self.activation_deriv=logistic_derivative
elif activation=='tanh':
self.activation=tanh
self.activation_deriv=tanh_derivative
self.weight=[]
for i in range(1,len(layers)-1):
#print(layers[i - 1] + 1, layers[i] + 1)
#print(layers[i] + 1, layers[i + 1] + 1)
self.weight.append((2 * np.random.random((layers[i - 1] +1, layers[i] +1)) - 1) * 0.25)
self.weight.append((2 * np.random.random((layers[i] +1, layers[i + 1])) - 1) * 0.25) #print("weight:", self.weight) def fit(self,X,Y,learning_rate=0.2,epochs=10000):#数据集,目标标记,学习速率,最大学习次数 #神经网络是在抽样去训练。从数据集里随便抽一个去训练。
X=np.atleast_2d(X)#确认数据集至少是二维的。
temp=np.ones([X.shape[0],X.shape[1]+1]) #shape返回矩阵的行数与列数。对bias偏向定义初值
temp[:,0:-1]=X
X=temp
#print("X_:",X)
Y=np.array(Y)
#print("Y_:", Y)
for k in range(epochs):
i=np.random.randint(X.shape[0])
a=[X[i]]#随机抽取一个实例
#print("a_:", a)
for l in range(len(self.weight)):
a.append(self.activation(np.dot(a[l],self.weight[l])))#矩阵相乘然后代入激活函数
#print("l,a[l],weight[l]:",l, a[l],self.weight[l])
#print('a__',a)
#print("error:", l, Y[i], a[-1])
error =Y[i]-a[-1]
deltas =[error * self.activation_deriv(a[-1])] for l in range(len(a)-2,0,-1):
deltas.append(deltas[-1].dot(self.weight[l].T)*self.activation_deriv(a[l])) #算每一层的权重变化量
deltas.reverse()#翻转一下
for i in range(len(self.weight)):
layer = np.atleast_2d([a[i]])
delta = np.atleast_2d([deltas[i]])
self.weight[i]+=learning_rate*layer.T.dot(delta) #.T就是对矩阵的转置 def prdict(self,x):
x=np.array(x)
temp = np.ones(x.shape[0]+1)
temp[0:-1]=x
a=temp
for l in range(0,len(self.weight)):
a=self.activation(np.dot(a,self.weight[l]))
return a

这是写了一个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.会导致训练不成功

然后就可以写代码进行训练了

 from main import NeuralNetwork#导入刚才写的对象
import numpy as np nn=NeuralNetwork([2,2,1],'tanh') X = np.array([[0,0],[0,1],[1,0],[1,1]])
print("X:",X)
Y = np.array([1,0,0,1]) #也就是或运算嘛
print("Y:",Y)
nn.fit(X,Y)
#print("nn:",nn)
for i in [[0,0],[0,1],[1,0],[1,1]]:
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]

然后又写了一个手写数字识别的程序

 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() 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))

运行结果

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 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() nn=NeuralNetwork([,,])
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=)
prdictions=[]
for i in range(X_test.shape[]):
#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实现的更多相关文章

  1. 菜鸟之路——机器学习之KNN算法个人理解及Python实现

    KNN(K Nearest Neighbor) 还是先记几个关键公式 距离:一般用Euclidean distance   E(x,y)√∑(xi-yi)2 .名字这么高大上,就是初中学的两点间的距离 ...

  2. 菜鸟之路——机器学习之Kmeans聚类个人理解及Python实现

    一些概念 相关系数:衡量两组数据相关性 决定系数:(R2值)大概意思就是这个回归方程能解释百分之多少的真实值. Kmeans聚类大致就是选择K个中心点.不断遍历更新中心点的位置.离哪个中心点近就属于哪 ...

  3. 菜鸟之路——机器学习之SVM分类器学习理解以及Python实现

    SVM分类器里面的东西好多呀,碾压前两个.怪不得称之为深度学习出现之前表现最好的算法. 今天学到的也应该只是冰山一角,懂了SVM的一些原理.还得继续深入学习理解呢. 一些关键词: 超平面(hyper ...

  4. 【机器学习】BP神经网络实现手写数字识别

    最近用python写了一个实现手写数字识别的BP神经网络,BP的推导到处都是,但是一动手才知道,会理论推导跟实现它是两回事.关于BP神经网络的实现网上有一些代码,可惜或多或少都有各种问题,在下手写了一 ...

  5. 机器学习(4):BP神经网络原理及其python实现

    BP神经网络是深度学习的重要基础,它是深度学习的重要前行算法之一,因此理解BP神经网络原理以及实现技巧非常有必要.接下来,我们对原理和实现展开讨论. 1.原理  有空再慢慢补上,请先参考老外一篇不错的 ...

  6. 菜鸟之路——机器学习之决策树个人理解及Python实现

    最近开始学习机器学习,以下会记录我学习中遇到的问题以及我个人的理解 决策树算法,网上很多介绍,在这不复制粘贴.下面解释几个关键词就好. 信息熵(entropy):就是信息不确定性的多少 H(x)=-Σ ...

  7. 菜鸟之路——机器学习之非线性回归个人理解及python实现

    关键词: 梯度下降:就是让数据顺着梯度最大的方向,也就是函数导数最大的放下下降,使其快速的接近结果. Cost函数等公式太长,不在这打了.网上多得是. 这个非线性回归说白了就是缩小版的神经网络. py ...

  8. 菜鸟之路——机器学习之HierarchicalClustering层次分析及个人理解

    这个算法.我个人感觉有点鸡肋.最终的表达也不是特别清楚. 原理很简单,从所有的样本中选取Euclidean distance最近的两个样本,归为一类,取其平均值组成一个新样本,总样本数少1:不断的重复 ...

  9. 菜鸟之路——机器学习之线性回归个人理解及Python实现

    这一节很简单,都是高中讲过的东西 简单线性回归:y=b0+b1x+ε.b1=(Σ(xi-x–)(yi-y–))/Σ(xi-x–)ˆ2       b0=y--b1x-    其中ε取 为均值为0的正态 ...

随机推荐

  1. jq动态增加的button标签click回调失效的问题,即动态增加的button标签绑定事件$("button.class").click(function)无效

    对于新增加的页面元素,改变了页面结构,如果是使用老办法$("button.class").click(function)去监听新的button标签事件,会失效. 笔者的应用是文字的 ...

  2. xtrabackup支持的engine

    xtrabackup支持的engine 1.InnoDB/XtraDB Hot backup   2.MyISAM with read-lock   3.Archive,CSV with read-l ...

  3. 【BZOJ4650】[NOI2016] 优秀的拆分(后缀数组)

    点此看题面 大致题意: 定义将一个字符串拆成\(AABB\)的形式为优秀拆分,求一个字符串所有子串的优秀拆分个数. 后缀数组 这题可是一道后缀数组黑题啊. 其实看完题解这题还是挺简单的. 大致思路 显 ...

  4. 【转载】2018 hosts 持续更新访问 gu歌【更新于:2018-05-03】

      修改HOSTS实现免费,简单访问谷歌的目的   也是比较稳定的方法.修改hosts.修改hosts的方法,原理在于直接存储谷歌网站的IP地址.这样就不用DNS来解析网址了.也就是说,当我们输入谷歌 ...

  5. Incorrect key file for table './xx_db/xx_table.MYI'; try to repair it

    解决办法: 可以先运行 CHECK TABLE 表名 检查下是否存在错误. 然后运行 REPAIR TABLE 表名 进行修复.

  6. Spring Boot 2.x零基础入门到高级实战教程

    一.零基础快速入门SpringBoot2.0 1.SpringBoot2.x课程全套介绍和高手系列知识点 简介:介绍SpringBoot2.x课程大纲章节 java基础,jdk环境,maven基础 2 ...

  7. Ubuntu 14.04 LTS 触摸板无法使用

    c16b上,触摸板不能使用,查找后发现,需要在加载驱动时增加参数. 如下所说: 1.使用以下命令后,触摸板可以使用 sudo modprobe -r psmouse sudo modprobe psm ...

  8. Mybatis 插入一条或批量插入 返回带有自增长主键记录

    首先讲一下,  插入一条记录返回主键的 Mybatis 版本要求低点,而批量插入返回带主键的 需要升级到3.3.1版本,3.3.0之前的都不行, <dependency> <grou ...

  9. 使用Maven开发一个简单的SpringData

    1:创建Maven项目 2:添加依赖(修改pom.xml为以下代码) <project xmlns="http://maven.apache.org/POM/4.0.0" x ...

  10. c++ 操作符优先级

    优先级 操作符 描述 例子 结合性 1 ()[]->.::++-- 调节优先级的括号操作符数组下标访问操作符通过指向对象的指针访问成员的操作符通过对象本身访问成员的操作符作用域操作符后置自增操作 ...