机器学习(西瓜书)-BP神经网络实现

扫测资讯 2024-11-19 18:07   8 0

原理在书上

1、首先定义两个激活函数,越阶函数和sigmoid函数

2、用感知机实现线性可分的与,或,非问题,然后用多层感知机实现线性不可分的异或问题。

3、之后搭建了一个三层神经网络,任务是判断一个数字是否>0.5。

所有的参数还有变量依托于周志华的机器学习(西瓜书)p97-p104

import numpy as np
import matplotlib.pyplot as plt

def sgn(x):
    if x>=0:
        return 1
    else:
        return 0

def sigmoid(x):
    return 1/(1+np.e**(-x))
    # return x
x=np.linspace(-10,10,100)
y=[]
for i in x:
    y.append(sigmoid(i))
plt.plot(x,y)
plt.show()
import numpy as np
import matplotlib.pyplot as plt

def sgn(x):
    if x>=0:
        return 1
    else:
        return 0

def sigmoid(x):
    return 1/(1+np.e**(-x))
    # return x
x=np.linspace(-10,10,100)
y=[]
for i in x:
    y.append(sigmoid(i))
plt.plot(x,y)
plt.show()


w1=1
w2=1
d=2
print("\n与运算")
print("x1 x2 y")
for x1 in range(2):
    for x2 in range(2):
        y = sgn(x1 * w1 + x2 * w2 -d)
        print(x1,x2,y)

w1=1
w2=1
d=0.5
print("\n或运算")
print("x1 x2 y")
for x1 in range(2):
    for x2 in range(2):
        y = sgn(x1 * w1 + x2 * w2 -d)
        print(x1,x2,y)

w1=-0.6
w2=0
d=-0.5
print("\n非运算")
print("x1 y")
for x1 in range(2):
    for x2 in range(2):
        y = sgn(x1 * w1 + x2 * w2 -d)
        print(x1,y)



w1_1=1
w1_2=-1
w2_1=-1
w2_2=1
wh_1=1
wh_2=1
d=0.5
print("\n异或运算")
print("x1 x2 y")
for x1 in range(2):
    for x2 in range(2):
        h1 = sgn(x1 * w1_1 + x2 * w2_1 -d)
        h2 = sgn(x1 * w1_2 + x2 * w2_2 - d)
        y=sgn(h1 * wh_1 + h2 * wh_2 - d)
        print(x1,x2,y)
import numpy as np
import matplotlib.pyplot as plt

def sgn(x):
    if x>=0:
        return 1
    else:
        return 0

def sigmoid(x):
    return 1/(1+np.e**(-x))
    # return x



#
#    o       j={0}
#  / | \     whj[3,1]
# o  o  o    h={0,1,2}
#  \ | /     vih[1,3]
#    o       i={0}
x=np.random.random(100)
y=(x>0.5)*1.0
v=np.random.random([1,3])#v_ih
w=np.random.random([3,1])#w_hj
dh=np.random.random(3)#隐层的阈值
dy=np.random.random(1)#输出层阈值

def ah(h,xk):  #隐层h的输入
    sum=0
    for i in range(1):
        sum+=v[i][h]*xk
    return sum

def bh(h,xk): #隐层h的输出
    return sigmoid(ah(h,xk)-dh[h])

def Bj(j,xk): #输出层的输入
    sum=0
    for h in range(3):
        sum+=w[h][j]*bh(h,xk)
    return sum

def yj(j,xk): #输出层的输出
    return sigmoid(Bj(j,xk)-dy[j])

def Ek(xk,k): #损失
    sum=0
    for j in range(1):
        sum+=(yj(j,xk)-y[k])**2
    return (1/2)*sum

def gj(j,xk,k): #梯度计算
    return yj(j,xk)*(1-yj(j,xk))*(y[k]-yj(j,xk))


def eh(h,xk,k): #梯度项
    sum=0
    for j in range(1):
        sum+=w[h][j]*gj(j,xk,k)
    return bh(h,xk)*(1-bh(h,xk))*sum

def Model(x):
    a1=ah(0,x)
    a2=ah(1,x)
    a3=ah(2,x)

    b1=bh(0,x)
    b2=bh(1,x)
    b3=bh(2,x)

    B0=Bj(0,x)

    y_=yj(0,x)
    return y_>=0.5


def Precsion():
    good=0
    for k in range(100):
        # print(y[k]==Model(x[k])*1.0)
        if y[k] == Model(x[k]) * 1.0:
            good+=1
    print("准确率:",good,"%")


def train():
    n=0.1
    j=0#输出节点编号,只有一个节点
    loss=[]#记录损失变化
    c=0
    for b in range(200):#循环迭代次数
        for k in range(100):#对每个样本进行训练
            c+=1
            xk=x[k]
            loss.append(Ek(xk, k))
            d_whj_0=n*gj(j,xk,k)*bh(0,xk)
            d_whj_1=n*gj(j,xk,k)*bh(1,xk)
            d_whj_2=n*gj(j,xk,k)*bh(2,xk)

            d_dyj_0=-1*n*gj(j,xk,k)

            d_vih_0=n*eh(0,xk,k)*xk
            d_vih_1=n*eh(1,xk,k)*xk
            d_vih_2=n*eh(2,xk,k)*xk

            d_dh_0=-1*n*eh(0,xk,k)
            d_dh_1=-1*n*eh(1,xk,k)
            d_dh_2=-1*n*eh(2,xk,k)

            w[0][0] = w[0][0] + d_whj_0
            w[1][0] = w[1][0] + d_whj_1
            w[2][0] = w[2][0] + d_whj_2
            # print("w",w[0][0],w[1][0],w[2][0])
            dy[0] = dy[0] + d_dyj_0
            # print("dy",dy[0])

            v[0][0] = v[0][0] + d_vih_0
            v[0][1] = v[0][1] + d_vih_1
            v[0][2] = v[0][2] + d_vih_2
            # print("v",v[0][0],v[0][1],v[0][2])

            dh[0]=dh[0]+d_dh_0
            dh[1]=dh[1]+d_dh_1
            dh[2]=dh[2]+d_dh_2
            # print("dh",dh[0],dh[1],dh[2])
            # print("loss===========================================", Ek(k))
        Precsion()

train()
print(Model(0.54))
print(Model(0.44))
# plt.plot(range(c),loss)
# plt.show()