(西瓜书)神经网络(BP算法)代码详解

"""文件名:traindata.csv
编号	色泽	根蒂	敲声	纹理	脐部	触感	密度	含糖率	好瓜
1	青绿	蜷缩	浊响	清晰	凹陷	硬滑	0.697	0.46	是
2	乌黑	蜷缩	沉闷	清晰	凹陷	硬滑	0.774	0.376	是
3	乌黑	蜷缩	浊响	清晰	凹陷	硬滑	0.634	0.264	是
4	青绿	蜷缩	沉闷	清晰	凹陷	硬滑	0.608	0.318	是
5	浅白	蜷缩	浊响	清晰	凹陷	硬滑	0.556	0.215	是
6	青绿	稍蜷	浊响	清晰	稍凹	软粘	0.403	0.237	是
7	乌黑	稍蜷	浊响	稍糊	稍凹	软粘	0.481	0.149	是
8	乌黑	稍蜷	浊响	清晰	稍凹	硬滑	0.437	0.211	是
9	乌黑	稍蜷	沉闷	稍糊	稍凹	硬滑	0.666	0.091	否
10	青绿	硬挺	清脆	清晰	平坦	软粘	0.243	0.267	否
11	浅白	硬挺	清脆	模糊	平坦	硬滑	0.245	0.057	否
12	浅白	蜷缩	浊响	模糊	平坦	软粘	0.343	0.099	否
13	青绿	稍蜷	浊响	稍糊	凹陷	硬滑	0.639	0.161	否
14	浅白	稍蜷	沉闷	稍糊	凹陷	硬滑	0.657	0.198	否
15	乌黑	稍蜷	浊响	清晰	稍凹	软粘	0.36	0.37	否
16	浅白	蜷缩	浊响	模糊	平坦	硬滑	0.593	0.042	否
17	青绿	蜷缩	沉闷	稍糊	稍凹	硬滑	0.719	0.103	否
"""


import pandas as pd
import numpy as np
dataset = pd.read_csv('traindata.csv', delimiter="," ,encoding='gbk')

#according to P54--3.2
#process the dataset
attributeMap={}     #特征值字典
#色泽属性的三个取值(存在序的关系),所以可以用0,0.5,1 三个数表示;可参考西瓜书p54上方解释
attributeMap['浅白']=0
attributeMap['青绿']=0.5
attributeMap['乌黑']=1
#同上
attributeMap['蜷缩']=0
attributeMap['稍蜷']=0.5
attributeMap['硬挺']=1

attributeMap['沉闷']=0
attributeMap['浊响']=0.5
attributeMap['清脆']=1

attributeMap['模糊']=0
attributeMap['稍糊']=0.5
attributeMap['清晰']=1

attributeMap['凹陷']=0
attributeMap['稍凹']=0.5
attributeMap['平坦']=1

attributeMap['硬滑']=0
attributeMap['软粘']=1

attributeMap['否']=0
attributeMap['是']=1

del dataset['编号']
dataset=np.array(dataset)
m,n=np.shape(dataset)
for i in range(m):
    for j in range(n):
        if dataset[i,j] in attributeMap:    #如果该样本第i个样本的第j个特征的特征值在特征值字典中
            dataset[i,j]=attributeMap[dataset[i,j]]     #将数据集中第i个样本的第j个特征值数字化
        dataset[i,j]=round(dataset[i,j],3)      #round()函数作用:用于返回浮点数对应的四舍五入值,3表示四舍五入到小数点后三位

trueY=dataset[:,n-2]    #所有样本的标记列表
X=dataset[:,:n-2]       #所有样本的特征数据
m,n=np.shape(X)




#according to P101, 初始化参数
import random
d=n   #输入向量的维数(输入层8个神经元)
q=d+1   #隐层节点的数量(隐层9个神经元)
l=1   #输出向量的维数(输出层1个神经元)
theta=[random.random() for i in range(l)]   #输出节点的阈值(1个)
gamma=[random.random() for i in range(q)]   #隐层节点的阈值(9个)   注:输入层没有阈值和权重
# v size= d*q .输入节点和隐层节点之间的连接权重v(size=d*1,即维数和输入层向量维数相同)
v=[[random.random() for i in range(q)] for j in range(d)]   #逐行生成一个一个的随机数
# w size= q*l .隐层节点和输出节点之间的连接权重w(size=q*1,即维数和隐层向量维数相同)
w=[[random.random() for i in range(l)] for j in range(q)]
eta=0.2    #学习率
maxIter=5000 #最大迭代次数




import math
def sigmoid(iX,dimension):  #iX是一个有维数的矩阵;dimension表示维数(不准确,若iX是向量,dimension取1;若iX是矩阵,dimension取2)
    if dimension==1:    #若是向量,一次更新向量中的每个元素
        for i in range(len(iX)):   #若iX是向量,len(iX)表示向量的维数
            iX[i] = 1 / (1 + math.exp(-iX[i]))      #若iX是向量,iX[i]表示向量中第i个数
    else:   #若不是向量,递归拆分为一行一行的行向量
        for i in range(len(iX)):         #若iX是矩阵,len(iX)表示矩阵的行数
            iX[i] = sigmoid(iX[i],dimension-1)      #i若iX是矩阵,X[i]表示矩阵的第i行向量
    return iX





# do the repeat----standard BP
#每次迭代每个神经元要更新m次,但是这m次更新中相互之前可能会有影响
while(maxIter>0):
    maxIter-=1
    sumE=0
    for i in range(m):  #一个样本一个样本算
        alpha=np.dot(X[i],v)#p101 line 2 from bottom, shape=1*q   X[i]是第i个样本的特征向量
        b=sigmoid(alpha-gamma,1)#b=f(alpha-gamma), shape=1*q
        beta=np.dot(b,w)#shape=(1*q)*(q*l)=1*l
        predictY=sigmoid(beta-theta,1)   #shape=1*l ,p102--5.3
        #计算误差(观察用)
        E = sum((predictY-trueY[i])*(predictY-trueY[i]))/2    #5.4 此处的sum是去列表的作用  此处算出来的误差与下面的更新公式无关,只是print出来可以观察到单个样本的误差是多少
        sumE+=E#5.16    #每次迭代后所有样本的总误差
        #更新权值和阈值(训练用)
        g=predictY*(1-predictY)*(trueY[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  更新隐层节点和输出节点之间的连接权重w
        theta-=eta*g#5.12   更新输出节点的阈值
        v+=eta*np.dot(X[i].reshape((d,1)),e.reshape((1,q)))#5.13   更新输入节点和隐层节点之间的连接权重v
        gamma-=eta*e#5.14   更新隐层节点的阈值
    print(sumE)   #每更新一次总损失就越小




"""
#accumulated BP
#每次迭代每个神经元只更新一次,即用矩阵(向量)的方式让m个样本同时计算更新,并且这m个样本更新出来的权值和阈值相互之前不收影响
trueY=trueY.reshape((m,l))   #把行向量转换为列向量
while(maxIter>0):
   maxIter-=1
   sumE=0
   alpha = np.dot(X, v)#p101 line 2 from bottom, shape=m*q
   b = sigmoid(alpha - gamma,2)  # b=f(alpha-gamma), shape=m*q
   beta = np.dot(b, w)  # shape=(m*q)*(q*l)=m*l
   predictY = sigmoid(beta - theta,2)  # shape=m*l ,p102--5.3
   # 计算误差(观察用)
   sumE = sum(sum((predictY - trueY) * (predictY - trueY))) / 2  # 5.4  每次迭代后所有样本的总误差   (predictY - trueY) * (predictY - trueY)和np.dot(predictY - trueY, predictY - trueY)是有区别的,前者直接用*是数据相乘,并非线性代数里的向量相乘,后者才是线代里的向量相乘(此处无法向量相乘)
   #体会sum除了把值相加外还有去除列表的作用
   #(predictY - trueY) * (predictY - trueY)=[[0.001709491750980586], [0.0015331872837118347]...]
   #sum((predictY - trueY) * (predictY - trueY))=[8.29007457992029]
   #sum(sum((predictY - trueY) * (predictY - trueY)))=8.29007457992029
   print(round(sumE,5))
   # 更新权值和阈值(训练用)
   g = predictY * (1 - predictY) * (trueY - predictY)  # shape=m*l p103--5.10
   e = b * (1 - b) * ((np.dot(w, g.T)).T)  # shape=m*q , p104--5.15
   w += eta * np.dot(b.T, g)  # 5.11 shape (q*l)=(q*m) * (m*l)
   theta -= eta * g  # 5.12
   v += eta * np.dot(X.T, e)  # 5.13 (d,q)=(d,m)*(m,q)
   gamma -= eta * e  # 5.14
"""



#通过输入样本的特征矩阵得到输出层的值
def predict(iX):
    alpha = np.dot(iX, v)  # p101 line 2 from bottom, shape=m*q
    b=sigmoid(alpha-gamma,2)#b=f(alpha-gamma), shape=m*q
    beta = np.dot(b, w)  # shape=(m*q)*(q*l)=m*l
    predictY=sigmoid(beta - theta,2)  # shape=m*l ,p102--5.3
    return predictY

print(predict(X))   #因为用的是sigmoid函数,所以输出的预测值表示的是测试样本为正例的概率

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用和引用,我找到了一个基于遗传算法优化的BP神经网络算法的MATLAB代码示例。以下是一个简单的示例: ``` % 创建神经网络 inputNum = 4; % 输入层神经元数量 hiddenNum = 8; % 隐层神经元数量 outputNum = 1; % 输出层神经元数量 net = patternnet([hiddenNum]); % 配置网络参数 net.trainParam.showWindow = false; % 不显示训练窗口 net.trainParam.epochs = 1000; % 训练迭代次数 % 导入训练数据 load('training_data.mat'); % 假设训练数据存储在training_data.mat文件中 inputs = training_data.inputs; % 输入数据 targets = training_data.targets; % 目标数据 % 使用遗传算法优化训练 ga = gaoptimset('PopulationSize', 50, 'Generations', 100); net = train(net, inputs, targets, 'UseParallel', 'yes', 'UseGPU', 'no', ... 'TrainFcn', 'trainscg', 'adaptFcn', 'madapt1', 'mdistance', 'dist'); % 测试网络 load('test_data.mat'); % 假设测试数据存储在test_data.mat文件中 testInputs = test_data.inputs; % 测试输入数据 testTargets = test_data.targets; % 测试目标数据 testOutputs = net(testInputs); % 使用训练好的网络进行预测 % 计算均方根误差(RMSE) rmse = sqrt(mean((testOutputs - testTargets).^2)); disp(['均方根误差(RMSE): ', num2str(rmse)]); ``` 请注意,这只是一个示例代码,并且需要根据你的实际情况进行修改。你需要替换训练数据和测试数据的导入部分,并根据你的数据集和网络结构修改参数。另外,这个示例使用了"trainscg"训练函数和"madapt1"自适应函数,你也可以根据需要选择其他合适的训练函数和自适应函数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [matlab实现神经网络算法,人工神经网络matlab代码](https://blog.csdn.net/aifamao6/article/details/126886782)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [基于Matlab的遗传算法优化BP神经网络算法实现(附算法介绍与代码详解)](https://blog.csdn.net/DigitalGeo/article/details/124427728)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值