动态网站建设优缺点免费写文章的软件
神经网络基础
神经网络可以处理结构化数据(表格、数据库等)和非结构化数据(图像、音频等),并用于训练如房子特征和房价之间的函数、训练图像和类别之间的函数、训练语音和文本之间的函数等,从而实现房价预测、图像分类、语音识别等功能。
为何最近神经网络崛起了呢,下面引用吴恩达的一幅图片进行解释。当数据(带标签的)量比较小的时候,传统学习算法的效果和神经网络的效果差异不大,当数据量变大之后,神经网络的效果要明显好于传统学习算法(支持向量机、逻辑回归等),得益于廉价相机的推广和物联网的发展,传感器不断生成各种数据,数据量越来越大,此时神经网络的表现就要好于传统学习算法。
神经元
如下图,假设现在有两类数据分别代表猫、狗,区分这两类数据最简单的方法就是在中间画一条直线把数据分成两类,新的向量只要在直线下方的就是猫,直线上方的是狗,神经元就是把特征空间一切两半,认为两半分别属两个类。神经元一刀把空间切成两半
在上一篇文章《python实现手写数字识别》里已经讲过,这个就是逻辑回归,
,一个神经元其实就是逻辑回归分类器,如下图。神经元
神经网络
神经元(逻辑回归)虽然简单好用,但是有个缺点,就是只能切一刀,如果遇到复杂的情况就处理不了了。如下图就无法用一条直线把两类分开。一刀无法切开两类数据
这时候你会想,如果能过多切几刀就好了,没错!这种复杂情况的分类方法就是通过多层神经网络,每切一刀其实就是使用一个神经元,只要你切足够多刀,理论上你可以表示很复杂的函数分布。下面就是神经网络的表示图,每一个神经元的输出作为下一层神经元的输入。神经网络模型
用python实现神经网络由于篇幅所限,此处不展开介绍反向传播算法及其数学推导、正则化、梯度检测,后续将单独写一篇文章来介绍。
我们继续选择手写数字识别问题作为例子建立神经网络,并检验其预测的准确率。每一条数据是长度为400的向量。
1.选择神经网络框架以及随机初始化权重
因为输入的是长度400的向量,输出是0-9的数字分类结果,因此输入层神经元数量是400,输出层神经元数量是10,隐藏层神经元的数量我们选择40个,Hidden Layer与Input Layer之间的联系定义为权重Θ1(包含了bias unit),Output Layer与Hidden Layer之间的权重定义为Θ2(包含了bias unit),则Θ1是形状为(25,401)的矩阵,Θ2是形状为(10,62)的矩阵。
当将所有参数初始化为零的时候,会使所有的节点变得相同,在训练过程中只能学到相同的特征,而无法学到多层级、多样化的特征。解决办法是随机初始化所有参数,但仅需少量的方差就行。这里我们给Θ1,Θ2分别初始化一个很小的初始值。
#神经网络框架为400*25*10
input_layer_size = 400
hidden_layer_size = 25
output_layer_size = 10
n_training_samples = X_train.shape[0]
#随机初始化Thetas
def genRandThetas():
epsilon_init = 0.12
theta1_shape = (hidden_layer_size, input_layer_size+1)
theta2_shape = (output_layer_size, hidden_layer_size+1)
rand_thetas = [np.random.rand( *theta1_shape ) * 2 * epsilon_init - epsilon_init,
np.random.rand( *theta2_shape ) * 2 * epsilon_init - epsilon_init]
return rand_thetas
2.执行前向传播,计算每一个x对应的h(x)
第一步我们已经建立了如下的三层神经网络如下图:
如上图,
代表第l层第i个神经元指向第l+1层第j个神经元的权重,x是特征值,
是第l层的输出。下面我们来从第一层开始计算神经元的输出值(忽略bias unit),知道计算出h(x)。
第一层各神经元的输出就是各特征值,即:
第二层各个神经元的输出如下,p为第一层神经元的个数400,q为第二层神经元的个数40:
...
写成向量化形式为:
同理,第三层各神经元的输出向量化为:
def propagateForward(row,Thetas):
feature = row
zs_as_per_layer = [] #储存各层神经网络的z值和a值
for i in range(len(Thetas)):
theta = Thetas[i]
z = np.dot(feature,theta.T).reshape(theta.shape[0],1)
a = expit(z)
zs_as_per_layer.append((z, a))
if i == len(Thetas)-1:
return np.array(zs_as_per_layer)
a = np.insert(a,0,1) #Add bias unit
feature = a.T
3.计算损失函数
损失函数Cost function是预测值与真实值之间的偏差的总和,我们回忆一下逻辑回归中的损失函数:
神经网络的损失函数也是类似的,神经网络的输出层有K个神经元(逻辑回归),因此损失函数为:
def computeCost(myThetas,myX,myy):
myThetas = reshapeParams(myThetas)
myX = reshapeX(myX)
m = n_training_samples
total_cost = 0.
for i in range(m):
myrow = myX[i]
myhs = propagateForward(myrow,myThetas)[-1][1]
tmpy = np.zeros((10,1))
tmpy[myy[i]-1] = 1
mycost = -tmpy.T.dot(np.log(myhs))-(1-tmpy.T).dot(np.log(1-myhs))
total_cost += mycost
total_cost = float(total_cost)/m
return total_cost
4.使用反向传播算法计算梯度
使用梯度下降或者其他高级最优化算法,总是要求出C关于θ的导数,即
。使用前向传播求导计算量非常大,而反向传播算法求梯度可以大大减少计算的次数。
如下图,首先通过前向传播传递信息直到产生误差(低了、高了),再通过反向传播传递误差信息,更新权重矩阵。由于反向传播算法比较复杂,此处就直接使用了,原理及数学推导后续会单独写一篇,有兴趣的同学可以期待一下哦
首先记损失函数C关于l层的第j个元素的偏导为:
根据反向传播四大公式,即可求出梯度
def backPropagate(myThetas,myX,myy):
myThetas = reshapeParams(myThetas)
m = n_training_samples
myX = reshapeX(myX)
Delta1 = np.zeros((hidden_layer_size,input_layer_size+1))
Delta2 = np.zeros((output_layer_size,hidden_layer_size+1))
for i in range(m):
myrow = myX[i]
a1 = myrow.reshape((input_layer_size+1,1))
temp = propagateForward(myrow,myThetas)
z2 = temp[0][0]
a2 = temp[0][1]
z3 = temp[1][0]
a3 = temp[1][1]
tmpy = np.zeros((10,1))
tmpy[myy[i]-1] = 1
delta3 = a3 - tmpy
delta2 = myThetas[1].T[1:,:].dot(delta3)*sigmoidGradient(z2)
a2 = np.insert(a2,0,1,axis=0)
Delta1 += delta2.dot(a1.T)
Delta2 += delta3.dot(a2.T)
D1 = Delta1/float(m)
D2 = Delta2/float(m)
return flattenParams([D1, D2]).flatten()
5.利用最优化算法最小化损失函数
根据损失函数以及梯度,使用最优化算法如梯度下降等,即可求解Θ,得到预测函数h(x)。
def trainNN():
randomThetas_unrolled = flattenParams(genRandThetas())
result = scipy.optimize.fmin_cg(computeCost,x0=randomThetas_unrolled,
fprime=backPropagate,args(X_train,y_train),
maxiter=50,disp=True,full_output=True)
return reshapeParams(result[0])
6.计算手写数字识别的准确度
使用测试集得到我们的神经网络预测准确度为93.9%,对比我们上一期的逻辑回归的预测准确率89.1%,有了明显的提高,神经网络的强大可见一斑。
欢迎关注我的专栏:python实现机器学习算法zhuanlan.zhihu.com