赞
踩
目录
我们在上一节课中说到,随着输入数据的特征越来越多,如果一个个的去编写函数表达式未免有点麻烦和拖沓,所以我们需要一个数学工具让这件事情变得简单,矩阵和向量。
一个方程可用向量运算:(简洁、统一)
一组函数可用矩阵运算:
numpy矩阵运算:
将上节课代码中数组转化为向量替代:
之前代码
- import numpy as np
- import dataset
- import plot_utils
-
- m = 100
- xs, ys = dataset.get_beans(m)
- print(xs)
- print(ys)
-
- plot_utils.show_scatter(xs, ys)
-
- w1 = 0.1
- w2 = 0.2
- b = 0.1
-
- ## [[a,b][c,d]]
- ## x1s[a,c]
- ## x2s[b,d]
- ## 逗号,区分的是维度,冒号:区分的是索引,省略号… 用来代替全索引长度
- # 在所有的行上,把第0列切割下来形成一个新的数组
- x1s = xs[:, 0]
- x2s = xs[:, 1]
-
- # 前端传播
- def forward_propgation(x1s, x2s):
- z = w1 * x1s + w2 * x2s + b
- a = 1 / (1 + np.exp(-z))
- return a
-
- plot_utils.show_scatter_surface(xs, ys, forward_propgation)
-
- for _ in range(500):
- for i in range(m):
- x = xs[i] ## 豆豆特征
- y = ys[i] ## 豆豆是否有毒
- x1 = x[0]
- x2 = x[1]
-
- a = forward_propgation(x1, x2)
-
- e = (y - a) ** 2
-
- deda = -2 * (y - a)
- dadz = a * (1 - a)
- dzdw1 = x1
- dzdw2 = x2
- dzdb = 1
-
- dedw1 = deda * dadz * dzdw1
- dedw2 = deda * dadz * dzdw2
- dedb = deda * dadz * dzdb
-
- alpha = 0.01
- w1 = w1 - alpha * dedw1
- w2 = w2 - alpha * dedw2
- b = b - alpha * dedb
-
- plot_utils.show_scatter_surface(xs, ys, forward_propgation)
使用向量矩阵后的代码vec_caculate.py:
- import numpy as np
- import dataset
- import plot_utils
-
- m = 100
- X, Y = dataset.get_beans(m)
- print(X)
- print(Y)
-
- plot_utils.show_scatter(X, Y)
-
- # w1 = 0.1
- # w2 = 0.2
- W = np.array([0.1, 0.1])
- # b = 0.1
- B = np.array([0.1])
-
- # 前端传播
- def forward_propgation(X):
- # z = w1 * x1s + w2 * x2s + b
- # ndarray的dot函数:点乘运算
- # ndarray的T属性:转置运算
- Z = X.dot(W.T) + B
- # a = 1 / (1 + np.exp(-z))
- A = 1 / (1 + np.exp(-Z))
- return A
-
- plot_utils.show_scatter_surface(X, Y, forward_propgation)
-
- for _ in range(500):
- for i in range(m):
- Xi = X[i] ## 豆豆特征
- Yi = Y[i] ## 豆豆是否有毒
-
- A = forward_propgation(Xi)
-
- E = (Yi - A) ** 2
-
- dEdA = -2 * (Yi - A)
- dAdZ = A * (1 - A)
- dZdW = Xi
- dZdB = 1
-
- dEdW = dEdA * dAdZ * dZdW
- dEdB = dEdA * dAdZ * dZdB
-
- alpha = 0.01
- W = W - alpha * dEdW
- B = B - alpha * dEdB
-
- plot_utils.show_scatter_surface(X, Y, forward_propgation)
从本节课开始,为了能够快速的上手实现,我们就不再手写神经网络的实践,而使用机器学习框架Keras,让他帮我们彻底摆脱各种底层麻烦的事情。所以Keras框架到底是什么?对于有计算机基础的同学来说,我们可以做一个类比进行理解,我们用汇编语言写程序也是可以的,可是那太麻烦了,你必须完全了解你所面对的机器有多少的寄存器,RAM有多少,怎么分布的,如何响应中断。
所以人们发明的C语言一下子就让我们很大程度上摆脱了计算机底层硬件的琐碎问题,而能专注于编写我们想要的功能。当然,在使用C语言的时候,我们必要时还需要考虑一些底层的琐碎问题,人们希望编程更简单,更注重业务而不是机器,所以出现了Java 、c#等等这些更加上层的语言,直到Python、javascript这种脚本语言的出现,我们几乎不太需要关心底层到底发生了什么。
Keras框架就像机器学习里的高级语言,实现了对机器学习神经网络底层复杂的数学运算的封装,我们可以轻松的通过它提供了各种上层接口搭建模型。当然除了Keras以外,还有很多其他的框架,比如最耳熟能详的TenSorflow,还是用编程语言来举例子,Tensorflow更像是C语言,对底层的封装并不是那么完全,但是更加的强大和灵活。而Keras更像是python语言,就两个字,简单。我们可以类比一下一个同样的神经元模型,用Keras和Tensorflow框架实现的代码量,你会很直观的看见它们的区别。
但不论Keras如何简单,我们也不能在完全不懂底层原理的情况下去使用它,就像不论你使用C语言还是python语言编程,都断然不可完全不懂计算机基本原理一样。或许你能做出一点东西,但最终会很虚无缥缈,也很难向更高的地方前进。
Keras框架搭建小蓝的大和之前作对比:
手撸模型:之前为了实现一个简单的神经元,也需要编写各种繁琐的代码,首先是前向传播,然后是计算代价函数,再然后利用反向传播计算误差在每个神经元上的权重和偏置参数的导数进行梯度下降。这些过程想想就很繁琐。
现在如果我们想要把神经元变成两个,你只需要把unite=1改成unite=2就可以了。
当然,我们的豆豆分类作为一个分类问题,只有一个0或1的单输出,两个神经元有两个输出,所以我们需要在后面再加一个神经元,把这两个神经元汇合一下。如果你想让这个模型更加复杂也更强大一点,比如把第一层的神经元数量改成四,同样也只需要简单的把1设置为4即可。
这就是我们的Keras框架,作为机器学习神经网络的应用入门,它的极致简单简直就是福音。
我们打开Keras的文档,正如它的第一段话说的那样,你恰好发现的Keras。那说完Keras的酸爽,我们也简单的介绍一下它存在的一些问题。首先,这如文档里说的那样,Keras并不是一个独立的框架,而是通过调用诸如Tensorflow、CNTK或Theano等独立的框架实现的。你可以简单的类比编程语言中python语言的运行环境,使用更底层一点的C或C++写成的。第二,就因为它太简单了,封装的太好了,所以有时候并没有像更加底层的Tensorflow那样灵活。虽然他说高度模块化可扩展性,但众所周知,往往高度封装带来的简单会造成对具体细节控制的流失。当然,经过这么多年的发展,Keras在灵活性上也在不断的增强,而作为同出谷歌之首的两大框架,目前也已经把Keras并入到了Tensorflow之中,作为Tensorflow的高级API。但问题是,如果我使用Keras去做这么细致的事情,那为什么不使用Tensorflow?正如我们在面对谁是最好的编程语言这个问题一样,答案是一致的,没有最好,只有最合适。Keras 的开发重点是支持快速
的实验。能够以最小的时延把你的想法转换为实验结果,是做好研究的关键。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。