基于python2的一个简单的bp神经网络的实现过程

#在这里首先声明的是有参考下面的这个博客中内容

#https://blog.csdn.net/bixiwen_liu/article/details/52956727权重的设置
#http://www.neurta.com/node/342
import numpy as np
import random
import string
def sigmoid(x):
    return 1/(1+np.e**(-x))
def sigmoidqiudao(y):
    return y*(1-y)
def tanh(x):
    return (np.e**x-np.e**(-x))/(np.e**x+np.e**(-x))
def tanhqiudao(y):
    return 1-np.square(y)
def createweightmatric(row,column):
    #这里的行和列,分别表示的是两个相邻层之间神经元的个数
    a=round(random.uniform(0, 1), 1)
    #uniform可以生成范围内的随机小数,round用来设置保留小数点的位数,这样的设置可以让我们在进行权重赋值的时候每次都保证权重的充分随机性
    weightsmatric=np.mat(np.random.uniform(a,-a,size=(row,column)))
    return weightsmatric
class Nerualnetwork:
    #初始化各项参数,这里主要设置了四个参数,输入层的神经元的个数,隐藏层的神经元的个数,输出层的神经元的个数。
    def __init__(self,num_input,num_hidden,num_out):
        self.num_input=num_input+1
        #这里进行加1的主要目的是为了,在这一个神经元中存储偏值b
        self.num_hidden=num_hidden
        self.num_out=num_out
        self.hiddenprint=[1.0]*self.num_hidden
        self.outprint=[1.0]*self.num_out
        self.weightsmatrix1=np.zeros((num_hidden,num_input+1))
        self.weightsmatrix2=np.zeros((num_out,num_hidden))
        self.input=[1.0]*(self.num_input-1)
        #对各个层进行激活
    def train1(self,input):
        #进行判断看设置的各个层的神经元的个数是否与实际输入的数据类型相符
        if len(input) !=self.num_input-1:
            raise ValueError('与输入层节点数不符!')
        for i in range(self.num_input-1):
            self.input[i]=input[i]
#         return lst
        for i in range(self.num_hidden):
            result1=[]
            for j in range(self.num_input-1):
                self.weightsmatrix1=createweightmatric(self.num_hidden,self.num_input)
                #这里之所以这样设置是为了后面的 矩阵乘法能够满足神经网络的原理
                result1.append(self.input[j]*self.weightsmatrix1[i,j])
                #矩阵的行和列的下标都是从0开始的,而range出来的也是从0开始的,上面的
            self.hiddenprint[i]=(tanh(sum(result1)+self.weightsmatrix1[i,self.num_input-1]))
            #这里的+self.weightsmatrix1[i,self.num_input-1]表示的是加上阈值b因为在创建权重矩阵的时候我们对self.num_input进行了加1操作
            #在创建的矩阵的最后一列我们多保存了一列随机数,这一列随机数我们我们把它们作为隐藏层各个神经元的偏置值。
            #这步时对输出层所有神经元指向隐藏层的权重及input乘积之和,对隐藏层的神经元逐个遍历
        result3=[]
        lst2=[]
        for each in  self.hiddenprint:
            lst2.append(each)
        for k in range(self.num_out):
            for l in range(self.num_hidden):
                self.weightsmatrix2=createweightmatric(self.num_out,self.num_hidden)
                result3.append(lst2[l]*self.weightsmatrix2[k,l])
            self.outprint[k]=(sigmoid(sum(result3)+self.weightsmatrix2[k,self.num_hidden-1]))
        return self.outprint
    #这里应该还可以进行简化。
    def updateweight2(self,targets,N):
        if len(targets)!=self.num_out:
            raise ValueError('与输出层节点数不符!')
            
        output_deltas = [0.0] * self.num_out
        for k in range(self.num_out):
        #对输出层的每一个神经元进行遍历
            error = targets[k]-self.outprint[k]
            #对0.5*(targets[k]-self.outprint[k])**2进行求导
            output_deltas[k] = tanhqiudao(self.outprint)[k] * error
        #计算误差的传递公式,下面的误差的传递都是根据这一原理进行的计算
        # 计算隐藏层的误差
#         output_deltas
        hidden_deltas = [0.0] * self.num_hidden
        for j in range(self.num_hidden):
            error = 0.0
            for k in range(self.num_out):
                error =error+output_deltas[k]*self.weightsmatrix2[k,j]
                #输出层的误差是由于前面一层的误差传递给它的所以这一层的误差等于前面的误差根据权重分配给它的
            hidden_deltas[j] = tanhqiudao(self.hiddenprint[j]) * error
#         hidden_deltas
#进行权值更新:
        for i in range(self.num_out):
            for j in range(self.num_hidden):
                bw=N*output_deltas[i]*self.hiddenprint[j]
                self.weightsmatrix2[i,j]=self.weightsmatrix2[i,j]+bw
#         self.weightsmatrix2
#输出层,每个神经元的误差都会向前传递给隐藏层的每一个神经元。因为刚开始在建立权重矩阵的时候,就是后面层做行前面层做列
        for i in range(self.num_hidden):
            for j in range(self.num_input-1):
                #这里之所以要进行减1操作时因为在weight1中最后一列是用来保存偏置值得,保存权重的只是前n-1列
                bw2=N*hidden_deltas[i]*self.input[j]
                self.weightsmatrix1[i,j]=self.weightsmatrix1[i,j]+bw2
#         self.weightsmatrix1
    #上面的操作只是对w的权重进行了更新并未对偏置b进行更行
    #下面的主要是对偏置值进行更新,主要有两层:一个是隐藏层另一个是输出层
        for i in range(self.num_out):
            bb1=N*output_deltas[i]
            self.weightsmatrix2[i,self.num_hidden-1]=self.weightsmatrix2[i,self.num_hidden-1]+bb1
#         self.weightsmatrix2,self.num_hidden-1这里之所以要进行减1操作是因为矩阵的行和列的下标均是从0开始的
        for j in range(self.num_hidden):
            bb2=N*hidden_deltas[j]
            self.weightsmatrix1[i,self.num_input-1]=self.weightsmatrix1[i,self.num_input-1]+bb2
#         self.weightsmatrix1
#         return hidden_deltas,output_deltas,self.weightsmatrix1,self.weightsmatrix2
        error = 0.0
        for k in range(len(targets)):
            error = error + 0.5*(targets[k]-self.outprint[k])**2
#         return error
            #用均方差定义损失函数
        return error
#         return self.weightsmatrix1,self.weightsmatrix2
    def train2(self,input):
        #进行判断看设置的各个层的神经元的个数是否与实际输入的数据类型相符
        if len(input) !=self.num_input-1:
            raise ValueError('与输入层节点数不符!')
        for i in range(self.num_input-1):
            self.input[i]=input[i]
#         return lst
        for i in range(self.num_hidden):
            result1=[]
            for j in range(self.num_input-1):
#                 self.weightsmatrix1=createweightmatric(self.num_hidden,self.num_input)
                #这里之所以这样设置是为了后面的 矩阵乘法能够满足神经网络的原理
                result1.append(self.input[j]*self.weightsmatrix1[i,j])
                #矩阵的行和列的下标都是从0开始的,而range出来的也是从0开始的,上面的
            self.hiddenprint[i]=(tanh(sum(result1)+self.weightsmatrix1[i,self.num_input-1]))
            #这里的+self.weightsmatrix1[i,self.num_input-1]表示的是加上阈值b因为在创建权重矩阵的时候我们对self.num_input进行了加1操作
            #在创建的矩阵的最后一列我们多保存了一列随机数,这一列随机数我们我们把它们作为隐藏层各个神经元的偏置值。
            #这步时对输出层所有神经元指向隐藏层的权重及input乘积之和,对隐藏层的神经元逐个遍历
        result3=[]
        lst2=[]
        for each in  self.hiddenprint:
            lst2.append(each)
        for k in range(self.num_out):
            for l in range(self.num_hidden):
#                 self.weightsmatrix2=createweightmatric(self.num_out,self.num_hidden)
                result3.append(lst2[l]*self.weightsmatrix2[k,l])
            self.outprint[k]=(sigmoid(sum(result3)+self.weightsmatrix2[k,self.num_hidden-1]))
        return self.outprint
    #这里应该还可以进行简化。
    def train3(self, patterns, iterations=3000, N=0.05):
        for p in patterns:
                inputs=p[0]
                targets=p[1]
                self.train1(inputs)
        for i in range(iterations):
            error = 0.0
            for p in patterns:
                inputs = p[0]
                targets = p[1]
                #如下面的例子所示列中含有两个元素,第一个为x,第二个为y.所以在数据输入时要注意数据的格式
                self.train2(inputs)
                error = error + self.updateweight2(targets, N)
                #self.backPropagate返回的时error
            if i % 100 == 0:
                print('误差 %-.5f' % error)
                #没迭代100次返回一个误差率
    def test(self, patterns):
        s=[]
        for p in patterns:
            t=self.train2(p[0])
            for each in t:
                if each>0.5:
                    each=[1]
                    s.append(each)
        #这里之所以要加[]是为了和后面的targets的数据保存格式保持一致
                else:
                    each=[0]
                    s.append(each)
        return s
    def weights(self):  
        print('Input weights:')  
        for i in range(self.num_hidden):  
            print(self.weightsmatrix1[i])  
        print()  
        print('Output weights:')  
        for j in range(self.num_out):  
            print(self.weightsmatrix2[j])  
def huafen(samples,percent):
    train=samples[0:int(round(len(samples)*(1-percent)))]
    return train
def huafen2(samples,percent):
    test=samples[-(int(round(len(samples)*percent))):]
    return test
#这个函数的主要作用是划分训练集和测试集,返回的是测试集,但是训练集怎么弄 ??
def caculate_accuracy(targets,outprint):
#这个函数可以用来计算预测结果的准确度
    c=0
    if len(targets) == len(outprint):
        for i in range(0, len(targets)):
        #两个列表对应元素相同,则直接过
            if targets[i] == outprint[i]:
                c=c+1
            else:#两个列表对应元素不同,则输出对应的索引
                pass
    t=(float(c)/len(targets))
    print t
    
    
def demo():
    # 一个演示:教神经网络学习逻辑异或(XOR)------------可以换成你自己的数据试试
    pat = [
        [[1,0,1,1,0,1,1,0,1], [0]],
        [[0,1,1,0,1,1,0,1,1], [1]],
        [[1,0,0,1,0,0,1,0,0], [0]],
        [[1,1,1,1,0,0,1,0,1], [1]],
        [[1,0,1,1,0,1,1,0,1], [0]],
        [[0,1,1,0,1,1,0,1,1], [1]],
        [[1,0,0,1,0,0,1,0,0], [0]],
        [[1,1,1,1,0,0,1,0,1], [1]],
        [[1,0,1,1,0,1,1,0,1], [0]],
        [[0,1,1,0,1,1,0,1,1], [1]],
        [[1,0,0,1,0,0,1,0,0], [0]],
        [[1,1,1,1,0,0,1,0,1], [1]],
        [[1,0,1,1,0,1,1,0,1], [0]],
        [[0,1,1,0,1,1,0,1,1], [1]],
        [[1,0,0,1,0,0,1,0,0], [0]],
        [[1,1,1,1,0,0,1,0,1], [1]],
        [[1,0,1,1,0,1,1,0,1], [0]],
        [[0,1,1,0,1,1,0,1,1], [1]],
        [[1,0,0,1,0,0,1,0,0], [0]],
        [[1,1,1,1,0,0,1,0,1], [1]],
        [[1,0,1,1,0,1,1,0,1], [0]],
        [[0,1,1,0,1,1,0,1,1], [1]],
        [[1,0,0,1,0,0,1,0,0], [0]],
        [[1,1,1,1,0,0,1,0,1], [1]]
        
        
    ]
#     pat = [
#         [[1,0], [0]],
#         [[0,1], [1]],
#         [[1,0], [0]],
#         [[1,1], [1]],
#         [[1,0], [0]],
#         [[0,1], [1]],
#         [[1,0], [0]],
#         [[1,1], [1]],
#         [[0,1], [1]],
#         [[1,0], [0]],
#         [[1,1], [1]]
#     ]


    # 创建一个神经网络:输入层有两个节点、隐藏层有两个节点、输出层有一个节点
    n = Nerualnetwork(9, 15, 1)
    # 用一些模式训练它
    n.train3(huafen(pat,0.3))
    pre=n.test(huafen2(pat,0.3))
    print pre
    targets=huafen2(pat,0.3)
    v=[]
    for each in targets:
        v.append(each[1])
    print v
    t=caculate_accuracy(v,pre)
    n.weights()
    
if __name__ == '__main__':
    demo()            

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值