文章目录

  • 前言
  • 一、机器学习是什么,深度学习是什么?
  • 二、对NN,CNN,RNN,GNN,GAN的名词解释
  • 三、详细介绍神经网络(NN)
    • 1.认识神经网络
    • 2.神经元
    • 3.激活函数
    • 4.权重——连接的线,连接结构
    • 5.正向传播
    • 6. 反向训练权重
  • 四、csv文件
  • 五、创建一个神经网络
  • 六、训练
  • 七、测试
  • 八、计算正确率

前言

minist手写数据集

随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


一、机器学习是什么,深度学习是什么?

机器学习分为监督学习,无监督学习和强化学习。

  • 监督学习相当于教小孩做题并告诉答案是什么,久而久之,AI会自己做题了,这种方法被用于各种识别任务,如人脸识别,车牌识别,肿瘤诊断;
  • 无监督学习就只有题目而没有答案了,AI只能根据自己观察到的特征,把认为相似的东西分为一组,虽然不知道谁是猫,谁是狗,但也能把它们区分出来,这种方法很适合从一堆东西中找到隐藏规律,就像对一堆颜色各异的积木,可以按形状分类,也可以按颜色分类,这一点比监督学习的用途要广(自发找特征);
  • 强化学习,这时AI不用做题,而是直接和环境互动,通过环境给出的奖惩来学习,目的是通过一系列动作获得最大的奖励,在互动的过程中,AI会不断调整自己的行为,对环境变化做出最佳的应对,这种方法常被用来训练行为,比如玩游戏,无人驾驶,推送广告等。

这三种方法经常被综合使用,让AI学会各种酷炫技能,比如最近兴起的一种训练方法GAN(生成对抗网络),它将两个AI放在一起,一个负责创作,一个负责找茬,通过来回对抗,最终训练一个创作达人,它可以无中生有,画出一张逼真的人脸,还能以假乱真搞艺术创作,画油画,写诗,作曲,都骗过了不少人,可以看到机器学习让AI越来越强大。
而深度学习就是监督学习。

二、对NN,CNN,RNN,GNN,GAN的名词解释

NN: Neural Network(神经网络)
CNN: Convolutional Neural Networks)(卷积神经网络)
RNN: Recurrent Neural Networks (循环神经网路)
GNN:Graph Neural Network(图神经网络)
GAN:Generative Adversarial Network(生成对抗网络)

CNN使得NN从二维转化到三维,加速了训练
RNN引入了时间的概念,比方说,“我今天去打篮球”,已知“我”,推测后面一个词是“今天”,一般用来NLP(自然语言处理)。
GAN将两个AI放在一起,一个负责创作,一个负责找茬,通过来回对抗,最终训练一个创作达人,它可以无中生有,画出一张逼真的人脸

三、详细介绍神经网络(NN)

1.认识神经网络

首先我们打开下面这个链接
神经网络模型

将num_neurons:1 改成1 后,点击simple data出现

把一个神经元比作切一刀,就相当于用一刀来切割图片的绿色和红色,而都改成2时,就会切两刀,会较好的分出红和绿的区分,如下:

  • 神经网络要做的事就是把红和绿给区分开,如果此时再出现一个点,我们不知道它是什么颜色,当它落入绿色的区域中,判定为绿色,当它落入红色的区域中,则判定为红色。
  • 就像你接触一个人,先看看它的朋友是个怎样的人,我们把这种算法叫做K临近算法。

2.神经元

现在我们把目光转向生物的神经元,神经元是怎样工作的呢,它接受一个电输入,输出一个电信号,看起来与机器一摸一样,这些机器也是接收一个输入,进行一些处理,然后弹出一个输出。

也许它的输出可能采取这样一种形式:输出 = (常数*输入)+(也许另一个常数)。

而另一方面,动物大脑表面上看起来以慢得多的节奏运行,却似乎以并行方式处理信号,模糊性是其计算的一种特征。

3.激活函数

但观察表明,神经元不会立即反应,而是会抑制输入,直到输入增强,就像直到水装满了杯子,才可能溢出——神经元不希望传递微小的噪音信号,而只是传递有意识的明显信号。

s(sigmod)阈值函数:  y = 1/1+e^-x
横坐标相当于是阈值,只有输入超过了阈值,才能产生输出信号。
总和输入值 x = a+b+c;
输出y  s阈值函数 y = y(x)

有趣的是,如果只有其中一个输入大,其他输入小也能激发神经元,更重要的是,如果其中单个一般大,组合足够大,超过阈值,那么也能激发。即这些神经元也可以进行一些相对复杂,在某种意义上有点模糊的计算。

4.权重——连接的线,连接结构

连接是神经元中最重要的东西。每一个连接上都有一个权重。
相当于两个神经元节点间的连接强度。

总和输入值x
x =a1*w1+a2*w2+a3*w3
S阈值输出
y = y(x)  #y = 1/1+e^-x

如果是两个输入节点。我们可以这样看

x = (第一个节点的输出*链接权重)+(第二个节点的输出*链接权重)
于是我们可以将它看作两个矩阵相乘
(w1 w2)*(a1    = w1*a1 + w2*a2a2)以此类推,如果是两个输出(w1,1 w2,1 * (a1  = (a1*w1,1 + a2*w2,1 w1,2  w2,2)   a2)    a1*w1,2 + a2*w2,2)这样我们无需花费太多精力就可以实现神经网络了。


连接结构,我们把前后层每一个神经元与其他神经元互相连接,我们不采用创造性的方式将神经元连接起来,原来有两个:第一个是这种完全连接形式可以相对容易地编码成计算机指令,第二是神经网络的学习过程将会弱化这些实际上不需要的连接(也就是这些连接的权重将趋近于0)。零权重意味着这个链接实际上是断开了。

我们把中间层称为隐藏层,其实并没有多大高深的含义。

权重是怎么得来的呢,我们先随机初始化这些数字,由于大的初始权重会造成大的信
号传递给激活函数,导致网络饱和,因此我们应该避免大的初始权重值,我们可以
从-1.0~+1.0之间随机均匀的选择。
数学家得到的经验法则是:从均值为0,标准方差等于节点传入链接数量平方根倒数
的正太分布中进行采样。(使累加的权重范围变小)
0权重和相同的权重是要避免的。
(np.random.rand(self.hnodes, self.inodes)-0.5)#函数只能生成[0,1]的浮点数,于是 -0.5使范围变成[-0.5,0.5],(self.hnodes, self.inodes)为矩阵行,列
(np.random.normal(0.0,pow(self.hnodes,-0.5),(self.hnodes, self.inodes)#均值为0,标准方差等于节点传入链接数量平方根倒数的正太分布中进行采样
lambda 匿名函数
<函数名> = lambda<参数>:<表达式>
f = lambda x,y,z :x+y+z

至此我们可以写出的神经网络对象

class neturalNetwork :# initialise the neural networkdef __init__(self,inputnodes,hiddennodes,outputnodes,learningrate ):# set numbers of nodes in each input ,hidden,output layerself.inodes = inputnodesself.hnodes = hiddennodesself.onodes = outputnodes# learning rateself.lr =learningrate# link weight matrices wih,who# weights inside the arrays are w_i_j,where link is from node i to node j in the next layer# w12 w21# w12 w22 etc# self.wih = (np.random.rand(self.hnodes, self.inodes) - 0.5)#随机初始化权重# self.who = (np.random.rand(self.onodes, self.hnodes) - 0.5)self.wih = (np.random.normal(0.0,pow(self.hnodes,-0.5),(self.hnodes, self.inodes)) )#较复杂的初始化权重self.who = (np.random.normal(0.0,pow(self.onodes,-0.5),(self.onodes, self.hnodes)) )# activation function is the sigmoid functionself.activation_function = lambda x: scipy.special.expit(x)#激活函数sigmod #使抑制输入 像生物一样pass

5.正向传播

根据以上,我们以3个输入层,3个隐藏层,3个输出层举例,

第一层 到 第二层
hidden_inputs = Wih * inputs#Wih 为input层到hidden层的权重矩阵
hidden_outputs = sigmod(hidden_inputs) #sigmod函数 加上阈值
第二层 到 第三层
final_inputs = Who * hidden_outputs#Who 为hidden层到output层的权重矩阵
final_outputs = sigmod(final_inputs)

由于输入的对象是以列的形式,所以我们要对输入的列表进行转置,并且矩阵拥有行和列,所以是2维的

inputs = np.array(input_list,ndmin=2).T#ndmin为定义数组最小维度 .T为转置

第一阶段,就是计算输出,所以我们正向查询的代码为

    def query(self,input_list):# convert inputs list to 2d arrayinputs = np.array(input_list,ndmin=2).T#ndmin为定义数组最小维度 .T为转置#calculate signals into hidden layerhidden_inputs=np.dot(self.wih,inputs)#calculate the signals emerging from hidden layerhidden_outputs=self.activation_function(hidden_inputs)#calculate signals into final layerfinal_inputs =np.dot(self.who,hidden_outputs)#calculate signals emerging from final layerfinal_outputs = self.activation_function(final_inputs)return final_outputspass

6. 反向训练权重

第二阶段 更新权重
首先我们得到误差,由目标矩阵减去最终矩阵

output_errors = targets -final_outputs

然后为隐藏层的误差构建矩阵,在输出层中,有两条路径对误差做出了“贡献”
分别为w1,1和w2,1,所以我们根据权重比例,对误差进行了分割,用e的一部分来更新w1,1:e*(w1,1/w,1,1+w2,1),类似的调整w2,1的e的部分为e*w2,1/(w1,1+w2,1),
这些分数的分母是一种归一化的因子,我们忽略这个因子,如果是两个输出节点

Error(hidden) = (w1,1  w1,2   *(e1    =(w1,1*e1+w1,2*e2w2,1  w2,2)    e2)      w2,1*e1 +w2,2*e2)

这个权重矩阵和我们先前构建的矩阵很像,容易发现是进行了转置,

Error(hidden) =Whidden_output.T *Erroroutput

我们现在获得了最终层的误差和隐藏层的误差,现在我们来更新权重。但是这些节点都不是简单的线性分类,这些稍微复杂的节点,对加权后的信号进行求和,,并应用了S阈值函数,将所得到的输出给下一层节点。但这个表达式太复杂了,我们不能硬碰硬的求解这个表达式。

换一个思路,想象一下,在一个非常复杂,有波峰波谷的地形以及连绵的群山峻岭。在黑暗中伸手不见五指。你知道你是在一个山坡上,你需要坡底。对于整个地形,你没有精确的地图,只有一把手电筒,你只能使用手电筒,做近距离的观察,你可以看到某一块土地看起来是下坡,于是就小步往下走,缓慢下山。

在数学上,我们称之为梯度下降,首先我们画一个简单的函数y = (x-1)^2 +1,
用y表示误差,我们希望找到x,可以最小化y,我们随机在线上取一点,当斜率为正就
向左移,斜率为负就向右移,我们要将步子调小,避免超调,在最小值的地方来回反
弹。

这次我们用复杂的三维空间,同时用高表示函数的值,这次我们的山谷有多个,但并不都是最低的山谷,我们会卡在错误的山谷吗?答案是肯定的。
为了避免这种事发生,我们从山上的不同点开始,多次训练神经网络。

epoch =5#训练的次数

我们可以使用梯度下降法,计算出正确的权重吗?只要我们选择了合适的误差函数,这完全是可以的。
之前我们已得到误差,我们很容易把输出函数变成误差函数。

误差值  = (目标值-实际值)^2
  • 使用误差的平方,我们可以很容易使代数计算出梯度下降的斜率。
  • 误差函数平滑连续,这使得梯度下降法很好地发挥作用——没有间断,也没有突然的跳跃
  • 越接近最小值,梯度越小,这意味着,我们使用这个函数调节步长,超调的风险就会变得较小。

要使用梯度下降,现在我们需要计算出误差函数相对于权重的斜率。也就是说我们想要知道“误差对链接权重的改变有多敏感”,这里我们会用到微分知识。
如果把网络连接权重(wi,j)为横坐标,神经网络误差(Error)为纵坐标,那么斜率就是

我们定义i,j,k,i为输入层,j为隐藏层,k为输出层
输出层输出ok,
节点误差=目标值 - 实际值 ek = tk -ok

我们反向传播,先看后两层,隐藏层和输出层
由微分的链式法则得

我们对上述式子各个击破,E = (tk-ok)^2,得到

ok是节点k的输出,如果你还记得,这是连续输入信号上进行加权求和,在得到的结果上应用函数得到的结果

由sigmod微分公式

带入,由于sigmod函数内部的表达式也需要对wj,k进行微分,因此我们对S函数微分项再次应用链式法则,这也非常容易,答案为oj,所以为

我们把2去掉,我们只关心斜率方向,ek = tk-ok

这就是我们所寻求的神奇表达式,也是训练神经网络的关键
以此类推输入层和隐藏层的误差函数斜率

更新后的权重wj,k是由刚刚得到的误差斜率取反来调整旧的权重而得到的

a为学习率,这个因子可以调节这些变化的长度,确保不会超调。
还是画出y = (x-1)^2+1,y为误差,x为权重
减号意味着,斜率为正就左移,减小误差
斜率为负就右移,减小误差
有点类似于牛顿迭代法,思想上是相同的


old-new = a *斜率

所以

表达式的最后一部分,是单行的水平矩阵,是之前输出的转置(之前输出是竖直的),因此通过这种形式可以让我们通过计算机编程语言高效的实现矩阵运算。
所以我们的反向训练代码为:

    # train the netural networkdef train(self,inputs_list,targets_list):#convert inputs list to 2d arrayinputs = np.array(inputs_list,ndmin=2).Ttargets =np.array(targets_list,ndmin=2).T# calculate signals into hidden layerhidden_inputs = np.dot(self.wih, inputs)# calculate the signals emerging from hidden layerhidden_outputs = self.activation_function(hidden_inputs)# calculate signals into final layerfinal_inputs = np.dot(self.who, hidden_outputs)# calculate signals emerging from final layerfinal_outputs = self.activation_function(final_inputs)# output layer error is the (target -actual)output_errors = targets -final_outputs# hidden layer error is the output_error,split by weights,recombined at hidden nodeshidden_errors = np.dot(self.who.T,output_errors)#update the weights for the links between the hidden and output layersself.who +=self.lr * np.dot((output_errors * final_outputs *(1.0- final_outputs)),np.transpose(hidden_outputs))#updata the weights for the links between the input and hidden layersself.wih +=self.lr * np.dot((hidden_errors * hidden_outputs *(1.0-hidden_outputs)),np.transpose(inputs))pass

四、csv文件

minist手写数据集
这意味着纯文本中的每一个值都是由逗号分隔的
第一个值是标签,随后的值是手写数字的像素值,28*28 为784个

#load the minist training data csv file into a list
training_data_file = open ("minist_dataset/mnist_train.csv","r")
training_data_list = training_data_file.readlines()
training_data_file.close()

五、创建一个神经网络

# number of input,hidden and output nodes
input_nodes = 784 #28*28
hidden_node = 200 #100#隐层在200以后不再变化
output_node = 10 #10分类# learning rate is 0.5
learning_rate = 0.1#学习率在0.1左右表现最佳# create instance of neural network
n =neturalNetwork(input_nodes,hidden_node,output_node,learning_rate)

六、训练

#training the neural network#epochs is the number of times the training data set is used for training
epochs =5#就是训练两遍for e in range(epochs):#5 或 7 达到一个最佳点
# go through all records in the traing data setfor record in training_data_list:#split the record by the ',' commas(逗号)all_values = record.split(',')#scale and shift(变换) the inputsinputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99)+0.01 #np.asfarray 将文本字符串转换为实数,并创建这些数字的数组# 使当前范围为0.01到0.99#create the target output values (all 0.01,except the desired label which is 0.99)targets = np.zeros(output_node) + 0.01#创建一个10分类的目标 ,除正确的是0.99其他都是0.01#all_value[0] is the target label for this recordtargets[int(all_values[0])] = 0.99#列如0的目标是[0.99,0.01,0.01,...]n.train(inputs,targets)pass

七、测试

创建一个列,答对了就写1,不对就写0

# test the neural network
scorecard =[]
for record in  test_data_list:all_values =record.split(',')correct_label = int(all_values[0])print(correct_label,"correct label")inputs = (np.asfarray(all_values[1:]) /255 *0.99 +0.01)outputs = n.query(inputs)label = np.argmax(outputs)#np.argmax发现数组的最大值并返回它的位置print(label,"network's answer")if (label == correct_label):scorecard.append(1)else:scorecard.append(0)passpass

八、计算正确率

# calculate the performance score ,the fraction(一小部分) of correct answers
scorecard_array = np.asarray(scorecard)
print("performance=",scorecard_array.sum() / scorecard_array.size)

【零基础】从零开始学神经网络《python神经网络编程》——手写数字识别实战相关推荐

  1. python svm实现手写数字识别——直接可用

    python svm实现手写数字识别--直接可用 1.训练 1.1.训练数据集下载--已转化成csv文件 1.2 .训练源码 2.预测单张图片 2.1.待预测图像 2.2.预测源码 2.3.预测结果 ...

  2. 卷积神经网络(cnn) 手写数字识别

    1. 知识点准备 在了解 CNN 网络神经之前有两个概念要理解,第一是二维图像上卷积的概念,第二是 pooling 的概念. a. 卷积 关于卷积的概念和细节可以参考这里12,卷积运算有两个非常重要特 ...

  3. 卷积神经网络案例:LeNet-5手写数字识别

    一.LeNet-5网络结构 1.1 LeNet-5介绍: 由Yann LeCun(杨立昆)于1998年提出的一种经典的卷积网络结构. 第一个成功应用于数字识别问题的卷积神经网络. 1.2 LeNet- ...

  4. Matlab卷积神经网络(CNN)手写数字识别(一)

    今天买的书到了,开始接触卷积神经网络,展示书中内容~ Matlab卷积神经网络手写数字识别(一) 机器学习的基本流程 加载Matlab自带数据集 机器学习的基本流程 在机器学习中,一般将数据集划分为两 ...

  5. 【手写数字识别】基于matlab GUI BP神经网络单个或连续手写数字识别系统【含Matlab源码 2296期】

    ⛄一.手写数字识别技术简介 1 案例背景 手写体数字识别是图像识别学科下的一个分支,是图像处理和模式识别研究领域的重要应用之一,并且具有很强的通用性.由于手写体数字的随意性很大,如笔画粗细.字体大小. ...

  6. Python人工智能--实现手写数字识别

    文章目录 一.K-近邻算法(KNN)概述 二.Python实现 三.Python实现手写数字识别 四.K值选取对数据准确率的影响 在做此项目之前,首先要明白何为KNN算法. 一.K-近邻算法(KNN) ...

  7. Python不同方法实现手写数字识别结果和代码

    一.背景 手写数字识别是符号识别的一个分支,虽然只是识别简单的10个数字,但却有着非常大的实用价值.在我们的日常生活中,每天都要进行大量的文档处理工作,比如税单,银行支票,汇款单,信用卡账单的处理,以 ...

  8. python实现神经网络数字识别_PYTHON搭建BP神经网络,并实现手写数字识别

    基本思路: 1.定义神经网络:定义输入层→定义隐藏层→定义输出层→找到权重和偏差→设置学习率→设置激活函数 2.定义训练网络:根据训练样本给出输出→根据输出结果,计算误差,根据误差反向更新隐藏层权重 ...

  9. 神经网络第一步,手写数字识别的例子分享给大家

    现在AI越来越火,其实很多东西真正懂了原理并不是这么高大上 这里给一个手动打造的简单神经网络做手写识别的例子 代码见 链接: https://pan.baidu.com/s/1boHxuCB 密码: ...

最新文章

  1. routeros v6.43.2_routeros软路由负载均衡,充分利用带宽,提高效率降低成本
  2. 判断IE浏览器的版本号
  3. boost::mpl模块实现zip_view相关的测试程序
  4. C代码+汇编 C的 函数汇编学习分析 rep stos dword ptr [edi]
  5. 解决spark-shell输出日志信息过多
  6. CAP 2.4版本发布,支持版本隔离特性
  7. 教你读懂Ajax的工作原理
  8. idea 远程调试_我的天!你竟然不会用IDEA远程调试Tomcat...
  9. “一云多Region”究竟能为企业解决什么问题?
  10. 红旗liuxe5.0下vmware tools安装记录
  11. python爬公众号文章_python爬取指定微信公众号文章
  12. shiro框架如何保持登录状态
  13. js实现跟浏览器 ctrl+f 一样的效果
  14. chrome去广告插件 去掉百度热搜
  15. LWIP网络开发从入门到精通
  16. 微信公众号二维码不同环境差异化处理
  17. 如何在Linux上使用快照包
  18. SAP F1 无法显示该网页 完美解决方案(不用重装SAP)
  19. Java线程的死锁和活锁
  20. Upload-Labs靶场 1-21全通关教程

热门文章

  1. 阿里云esc服务器真垃圾啊
  2. webpack错误之ERROR in mainModule not found: Error: Can‘t resolve ‘./src‘ in ‘C:\Users\tuchunrong\Progr
  3. P4117 [Ynoi2018] 五彩斑斓的世界 题解
  4. 线性代数|学习笔记|18.065MIT公开课 lecture05
  5. [Rx86OS-XIX] 应用程序和系统调用
  6. 《毕业论文新手入坑手册》分享
  7. 测试开发的瓶颈在哪儿?
  8. 2014年11月15日SIE赛意公司面试
  9. 穷游女生说:在川藏线上搭车,可以看清男人的本质
  10. 为什么你学过Java却忘光了——记第一次助教同学见面会,java开发面试笔试题