采用《机器学习》西瓜训练集3.0作为训练数据。
使用xlrd包从excel输入西瓜训练集
先是根据西瓜书54页,将离散属性连续化。然后初始化两组权值和阈值,取零到一之间随机数
隐层神经元个数设置为输入层+3个,学习率设置为0.3
![]() | |
---|---|
import numpy as np
import xlrd as xl
import random
import math
data=xl.open_workbook('watermelon.xlsx')
table = data.sheet_by_name('Sheet1')
m=table.nrows
n=table.ncols-1#编号不算
dataset={}
for mmp in range(m):
dataset[mmp]=table.row_values(mmp)
for mma in range(m):#编号不要,删掉,不知道为什么np.delete报错
del dataset[mma][0]
#p54,相同类型属性和不同属性
attributeSet={}
attributeSet['浅白']=0
attributeSet['青绿']=0.5
attributeSet['乌黑']=1
attributeSet['蜷缩']=0
attributeSet['稍蜷']=0.5
attributeSet['硬挺']=1
attributeSet['沉闷']=0
attributeSet['浊响']=0.5
attributeSet['清脆']=1
attributeSet['模糊']=0
attributeSet['稍糊']=0.5
attributeSet['清晰']=1
attributeSet['凹陷']=0
attributeSet['稍凹']=0.5
attributeSet['平坦']=1
attributeSet['硬滑']=0
attributeSet['软粘']=1
attributeSet['否']=0
attributeSet['是']=1
for i in range(m):
for j in range(n):
if dataset[i][j] in attributeSet:
dataset[i][j]=attributeSet[dataset[i][j]]
Y={}#这是判断结果(好瓜坏瓜)
for k in range(m):
Y[k]=dataset[k][n-1]
print(dataset[0][0])
X=np.zeros(shape=(m,n-1),dtype=float)
for l in range(m):
for l2 in range(n-1):
X[l][l2]=dataset[l][l2]
print(X)#X是属性转换为值得数组(不带结果)
n=n-1#X不带结果列方向降一维度
d=n#输入神经元个数
l=1#输出神经元个数
q=d+3#隐层神经元个数,随便定的,具体多少无定论
theta=[random.random() for i in range(l)] #输出节点阈值
gamma=[random.random() for i in range(q)] #输入节点阈值
v=np.zeros(shape=(d,q),dtype=float)
w=np.zeros(shape=(q,l),dtype=float)
for i in range(d):
for j in range(q):
v[i][j]=random.random()
for i in range(q):
for j in range(l):
w[i][j]=random.random()
eta=0.3 #学习率
maxIter=500 #训练次数
def sigmoid(iX,dimension):
if dimension==1:
for i in range(len(iX)):
iX[i] = 1 / (1 + math.exp(-iX[i]))
else:
for i in range(len(iX)):
iX[i] = sigmoid(iX[i],dimension-1)
return iX
while(maxIter>0):
maxIter-=1
sumE=0
a11,a22=np.shape(v)
for i in range(m):
alpha=np.dot(X[i],v)#p101
b=sigmoid(alpha-gamma,1)#b=f(alpha-gamma)
beta=np.dot(b,w)
predictY=sigmoid(beta-theta,1) #p102--5.3
E = ((predictY-Y[i])*(predictY-Y[i]))/2 #5.4
sumE+=E#5.16
#p104
g=predictY*(1-predictY)*(Y[i]-predictY)#shape=1*l p103--5.10
e=b*(1-b)*((np.dot(w,g.T)).T) #shape=1*q , p104--5.15
w+=eta*np.dot(b.reshape((q,1)),g.reshape((1,l)))#5.11
theta-=eta*g#5.12
v+=eta*np.dot(X[i].reshape((d,1)),e.reshape((1,q)))#5.13
gamma-=eta*e#5.14
def predict(iX):
alpha = np.dot(iX, v) # p101
b=sigmoid(alpha-gamma,2)#b=f(alpha-gamma), shape=m*q
beta = np.dot(b, w)
predictY=sigmoid(beta - theta,2)
return predictY
print(predict(X))
本来BP算法是自己闷头写的,然而写了老半天总有bug解决不了,最后还是参考了https://blog.csdn.net/qdbszsj/article/details/79110888的算法。对比我自己写的,这位老哥在求和上用了很多向量点积操作,我之前就没这个意识,都是手工一个个循环乘法,循环层次又长又臭还可读性差,有时间再慢慢改吧=_=