机器学习(1)--神经网络初探

来源:互联网 发布:sybase数据库实例教程 编辑:程序博客网 时间:2024/05/16 17:51
本文仅通过numpy,演示神经网络的计算方法,其实神经网络的计算相当于完成线性方程的求解,
当然,这个求解过程,不是线性方程的求解方法,而是通机器学习的神经网络方法进行求解,

本文的目的仅仅只是讲解神经网络的计算方法与流程,

离完善的代码还有很大的距离,你也可以使用如tensorflow等框架进行使用

可以参考我的另一篇文章  tensorflow实例(2)--机器学习初试


# -*- coding:utf-8 -*- import numpy as np'''双曲正切函数(tanh) 与 双曲函数,在神经网络运行过程要使用当,当然,这样的函数组不只这组,还有其他的,我们这里不研究数理,只是为了把神经网络计算的流程交待清楚,所以就不多做解释数理方面的东西,只要知道这在计算loss是用到就是'''def tanh(x):    return np.tanh(x)def tanh_deriv(x):    return 1.0 - np.tanh(x)*np.tanh(x)class npNN():    def __init__(self,w,b,layers):        '''            w 为线性方程上各维度的系数,            b为常数            即 y= a0 * x0 + a1 * x1 + a2 * x2  + a3 * x3 + b  其中w=[a0,a1,a2,a3]              layers,是指神经网络的中间层,特别强调,是中间层,如果为空则表示没有中间层            因为第一层即是w传参,最后一层的维度即是y值            下面的第一行就将对层数进行调整,形成完整的神经网络        '''        layers=[len(w)]+layers+[1] #补全神经网络层        w=(w if isinstance(w,np.ndarray) else np.array(w)).astype(np.float32)        #构建一100条数据,做为训练数据        x_data=np.random.random([100,len(w)]).astype(np.float32)        y_data=np.matmul(x_data,w)+b        #print(x_data[0]) #[ 0.00964573 , 0.17939466,  0.73853254 , 0.17505005]        #print(y_data[0]) #0.828423      即实现了线性方程  y =  0.00964573*0.1+ 0.17939466*0.2 + 0.73853254 *0.3+0.17505005*0.4+0.5        #------------------------------------------------开始:神经线(weights)的构建        weights=[]        for i in range(1,len(layers)-1):            #加入每两层间,神经节点连线的数量(神经线),注意在这句layers[i-1]+1,layers[i]+1,都有加1,这个1是在每层的维度上要加上一个biase            weights.append((np.random.random([layers[i-1]+1,layers[i]+1])-0.5)*0.5)         i=len(layers)-2        #加入指向倒数二层与与最后一层神经节点间,神经节点连线的数量(神经线),layers[i]+1,layers[i+1],这里倒数2层有加1,是biase,最后一层即y值,没有biase        weights.append((np.random.random([layers[i]+1,layers[i+1]])-0.5)*0.5)                #weights中的-0.5)*0.5,目的是为了产生的weights值在-0.25至0.25之间,数理问题不多说,这个例子只是为了演示过程        #简单的说,太大的数在双曲函数那算得会有问题        #np.random.random的目的是随机初始化weights,这里的目的只是给个初始值        #这和最终计算的没有任何关系,会在机器学习的过程中将不断的调整这些weights,        print('因为加上头尾共%d层,所以len(weights) = %d层 - 1 = %d'%(len(layers),len(layers),len(weights)))        for weight in enumerate(weights[:-1]):            print('神经第 %d 层的维度为 %s,其中%s为当前层的神经节点数,%s为下一层的神经节点数'%(weight[0]+1,np.array(weight[1]).shape,len(weight[1]),len(weight[1][0])))        print('神经第 %d 层的维度为 %s,其中%s为当前层的神经节点数,%s为最后一层的神经节点数'%(len(weights),np.array(weights[len(weights)-1]).shape,len(weights[len(weights)-1]),1))        '''        以下图示画出某两层之间的计算变化示例,,如某层共4个神经节点[a1,a2,a3,b1]  下一层为2个神经节点[c1,b2]        则这两层之间的weight维度即为[4,2] 用矩阵相乘表示                            [w1,w2]        [a1,a2,a3,b1]  *    [w3,w4] = [a1*w1+a2*w3+a3+w5+b1*w7  , a1*w2+a2*w4+a3+w6+b1*w8]  = [c1,b2]                            [w5,w6]                            [w7,w8]        倒数二层与最后一层也是一样的,只是最一层没有b,固定为一个值,weight维度即为[n,1],n由倒数二层决定        '''        print('-'*20+'完成神经线(weights)的构建'+'-'*20)        #------------------------------------------------结束:神经线(weights)的构建        #------------------------------------------------开始:神经线(weights)的计算        tmp=np.ones([x_data.shape[0],x_data.shape[1]+1])         tmp[:,:-1]=x_data#这几行构建一个用新数组,行数与x_data行数相同,列数比x_data列数加1,加的这个1即为biase  多出来的那列为值初设为1        x=tmp        for runTimes in range(1000):  #通过不断的循环,调整weights  主要包含正向的计算,逆向的修正两个步骤来完成            index = np.random.randint(len(x_data))#在x中取出任意一条            a=[x[index]] #放一个空数组中,赋值给a, 注意,在x[index] 外面有一层[],目的在于a后面会不断的append每层的神经计算结果              #------------------------------开始:通过从 第1层 到 最后一层 的 循环,计算出所有神经元的值            for k in range(len(weights)):                a.append(tanh(np.dot(a[k], weights[k]))) #计算的每层的的神经元的值np.dot(a[k], weights[l])  ,进行tanh转换后不断加入a数组            #循环结束后,最后一层就是计算出来的y值            error = y_data[index] - a[-1]            deltas = [error *tanh_deriv(a[-1])]   # 这两行计算出最后一层,即y层的误差,注意deltas是一个数组,外面有一层[],在后面会不断的append每层的误差            #------------------------------结束:通过从 第1层 到 最后一层 的 循环,计算出所有神经元的值            #------------------------------开始:逆向计算,调整所有的weights            #逆向计算,从倒数二层开始,            for l in range(len(a) - 2, 0, -1): # 从倒数二层开始                #用下一层的误差 * 当前 神经线的置换矩阵() * tanh_deriv(a[l])                deltas.append(deltas[-1].dot(weights[l].T)*tanh_deriv(a[l]))            deltas.reverse()  #倒序deltas数组,使得各元素也是从第一层开始            for i in range(len(weights)):                layer = np.atleast_2d(a[i])                delta = np.atleast_2d(deltas[i])                weights[i] += 0.2 * layer.T.dot(delta)  #0.2学习效率,应该是一个小于0.5的数,            #------------------------------结束:逆向计算,调整所有的weights            self.weights=weights    def predict(self,x):        #预测的过程,其实也就是上面的流程中,正向的走一次,计算出y值        x = np.array(x)        temp = np.ones(x.shape[0]+1)        temp[0:-1] = x        for l in range(0, len(self.weights)):            temp = tanh(np.dot(temp, self.weights[l]))        return tempprint('测试一:设置中间三层,每层的神经元为3个,2个,1个,特别注意,第一层及中间层都会加上一个biase')'''神经元图案如下@(a0)   @   @   @   @(y)@(a1)   @   @   @    @(a2)   @   @@(a3)   @   @(b)   '''test=npNN([0.01,0.02,0.03,0.04],0.05,[3,2,1])#print(a.weights)print(test.predict([1,1,1,1])) #实际值的结果应为0.01*1 +0.02*1 +0.03*1+0.04*1+0.05  =0.15print('\r\n测试二:设置无中层')'''神经元图案如下:计算测试二的目地,因为没有中间层,最后出来的wights共5个元素,也就是等于 [0.01,0.02,0.03,0.04],0.05@(a0)      @(a1)       @(a2)   @(y)@(a3)      @(b)   '''test=npNN([0.01,0.02,0.03,0.04],0.05,[])print(test.weights) #无中间层时,显示weigths,就和传参相当的接近了print(test.predict([1,1,1,1])) #实际值的结果应为0.01*1 +0.02*1 +0.03*1+0.04*1+0.05  =0.15


原创粉丝点击