• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

2022福大数学建模赛题B题-BP神经网络多分类Tensorflow-附python代码

武飞扬头像
渣渣zheng
帮助1

题目3:请根据附件 2 所提供的部分食物寒热属性(分为三类:性平、性温热、性凉寒),对附 件 1 中的食物进行分类,判断这些食物是属于性平、性温热或性凉寒中哪一类,并说明你分类的合理性;

BP神经网络:外部输入信号经输入层、隐含层的神经元的逐层处理,并向前传播至输出层从而获得结果。如果在输出层无法得到期望输出,则转入误差的反向传播过程,将网络输出实际值之间的误差沿原连接通路原路返回,通过修改各层神经元的连接权重,减小误差,然后转入正向传播过程,经过多次迭代,直至到达最大迭代次数或误差小于给定值为止。

学新通

 过程:

1、数据预处理。附件 1中 1284种食物,有 549种食物是已知其寒热属性,另外 735种食物的寒热属性未知。提取数据并归一化处理

2、构建模型。此时将食物各成分看成 BP神经网络模型的输入层,将 Y(寒热属性)当作模型的输出层。这里损失函数用的是均方误差。

3、正交实验设计。要考虑学习率、迭代次数、和神经元个数三个因素。各设置3个水平,采用正交实验的好处是,考虑了 3个因素彼此之间的交互作用,且减少实验的次数。

4、BP神经网络训练。得出的模型效果良好,但受参数影响较大。且训练时间随着问题规模以及神经元个数的增加而增加。

5、未知类别数据分类。利用训练出来的模型进行分类,并将分类结果标注在表中,并输出一个新的excel表。

python源代码:

注意:因变量Y需要映射为数值变量。因为后面的one-hot编码不能对字符串型状态编码,这点不同于哑变量(dummy)的处理。另外数据类型的转换也需要注意,因为这里面调用了一些已有的库,它们输入数据有些是array数组,dataframe表格,tensor张量等。还有就是神经网络训练时需要对已知数据集分成训练集和测试集,选择时尽量随机选择数据,避免训练集和测试集数据差异过大

  1.  
    import pandas as pd
  2.  
    import numpy as np
  3.  
    from sklearn import preprocessing
  4.  
    import re
  5.  
    import random
  6.  
    import tensorflow as tf
  7.  
     
  8.  
    df1 = pd.read_excel(r'食物成分表.xlsx', index_col=0).reset_index(drop=True)
  9.  
    df3 = df1.drop(['可食部分(%)'], axis=1)
  10.  
    scaler = preprocessing.MinMaxScaler() # 标准化
  11.  
    df33 = scaler.fit_transform(df3[df3.columns[1:17]]) # 训练和导出结果
  12.  
    df33 = pd.DataFrame(df33, columns=df3.columns[1:17]) # 数据格式转换
  13.  
    df3 = pd.concat([df3['名 称'], df33], axis=1)
  14.  
    df3['catef'] = '' # 添加分类列
  15.  
    print(df3.head()) # 查看前5条数据
  16.  
     
  17.  
     
  18.  
    # 根据附件2分类标注数据
  19.  
    def TagCategory(datastr, f, tap):
  20.  
    for line in f:
  21.  
    a = re.split('。|、|;|(|)|\\n| ', line) # 分割字符串保存到a
  22.  
    a = [x.strip() for x in a if x.strip() != ''] # 去除空字符串
  23.  
    for ss in a:
  24.  
    index0 = datastr.str.find(ss) # 找到则返回所要找字符串在指定字符串位置,没有则返回-1
  25.  
    ind = index0[index0.values != -1].index # 不为-1的即表示有
  26.  
    df3['catef'][ind] = tap # 标注
  27.  
     
  28.  
     
  29.  
    mingcheng = df3['名 称'].astype(str) # 提取名称所在列
  30.  
    f0 = open(r'性平.txt', encoding='utf-8')
  31.  
    f1 = open(r'性凉寒.txt', encoding='utf-8')
  32.  
    f2 = open(r'性温热.txt', encoding='utf-8')
  33.  
    TagCategory(mingcheng, f0, '性平') # 性平标
  34.  
    TagCategory(mingcheng, f1, '性凉寒') # 性凉寒标
  35.  
    TagCategory(mingcheng, f2, '性温热') # 性温热标
  36.  
    print(df3.head()) # 查看前5行
  37.  
     
  38.  
    NonNulldf = df3[(df3['catef'].notnull()) & (df3['catef'] != "")] # 找到所有已知类数据
  39.  
    IsNulldf = df3[(df3['catef'] == "")] # 找到未知类数据
  40.  
    kongindex = df3[(df3['catef'] == "")].index # 找到未知类数据的索引
  41.  
    print(NonNulldf.head())
  42.  
     
  43.  
    # 取数据方法:
  44.  
    data_train = NonNulldf
  45.  
    # 在初始数据划分训练集与测试集时直接将数据打乱:
  46.  
    data_train['catef']=data_train.catef.map({'性平':0,'性凉寒':1,'性温热':2})#分类列映射
  47.  
    DataIndex = [i for i in range(len(NonNulldf))]#产生索引
  48.  
    random.shuffle(DataIndex)#打算排序
  49.  
    data_train.index = [DataIndex]#新的排序
  50.  
     
  51.  
    x_train = data_train.iloc[0:round(0.95 * len(NonNulldf)), 1:17] # 取16个特征变量
  52.  
    y_train = data_train.iloc[0:round(0.95 * len(NonNulldf)), 17] # 后三列是因变量标签
  53.  
    x_test = data_train.iloc[round(0.95 * len(NonNulldf)):, 1:17] # 取16个特征变量
  54.  
    y_test = data_train.iloc[round(0.95 * len(NonNulldf)):, 17] #
  55.  
     
  56.  
    # 转换x的数据类型,否则后面矩阵相乘时会因数据类型不一致报错
  57.  
    x_train = tf.cast(x_train, tf.float32)
  58.  
    x_test = tf.cast(x_test, tf.float32)
  59.  
    # from_tensor_slices函数使输入特征和标签值一个一个地对应。(把数据集分批次,每个批次batch组数据)
  60.  
    train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)
  61.  
    test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
  62.  
     
  63.  
    # 生成神经网络的参数,16个输入特征,输入层为16个输入节点;因为3分类,故输出层为3个神经元
  64.  
    # 用tf.Variable()标记参数可训练
  65.  
    w1 = tf.Variable(tf.random.truncated_normal([16, 3], stddev=0.1)) # 16行三列,方差为0.1
  66.  
    b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1)) # 一行三列,方差为0.1
  67.  
     
  68.  
     
  69.  
    a = 0.4 # 学习率为0.4
  70.  
    epoch = 1000 # 循环1000轮
  71.  
    # 训练部分
  72.  
    for epoch in range(epoch): # 数据集级别的循环,每个epoch循环一次数据集
  73.  
    for step, (x_train, y_train) in enumerate(train_db): # batch级别的循环 ,每个step循环一个batch
  74.  
    with tf.GradientTape() as tape: # with结构记录梯度信息
  75.  
    y = tf.matmul(x_train, w1) b1 # 神经网络乘加运算
  76.  
    y = tf.nn.softmax(y) # 使输出y符合概率分布
  77.  
    y_ = tf.one_hot(y_train, depth=3) # 将标签值转换为独热码格式,方便计算loss
  78.  
    loss = tf.reduce_mean(tf.square(y_ - y)) # 采用均方误差损失函数mse = mean(sum(y-y*)^2)
  79.  
    # 计算loss对w, b的梯度
  80.  
    grads = tape.gradient(loss, [w1, b1])
  81.  
    # 实现梯度更新 w1 = w1 - lr * w1_grad b = b - lr * b_grad
  82.  
    w1.assign_sub(a * grads[0]) # 参数w1自更新
  83.  
    b1.assign_sub(a * grads[1]) # 参数b自更新
  84.  
    # 每1000次迭代,输出一次损失函数
  85.  
    if epoch % 10 == 0:
  86.  
    print('迭代第%i次,损失函数为:%f' % (epoch, loss))
  87.  
     
  88.  
     
  89.  
    # 测试部分
  90.  
    total_correct, total_number = 0, 0
  91.  
    for x_test, y_test in test_db:
  92.  
    # 前向传播求概率
  93.  
    y = tf.matmul(x_test, w1) b1
  94.  
    y = tf.nn.softmax(y)
  95.  
    predict = tf.argmax(y, axis=1) # 返回y中最大值的索引,即预测的分类
  96.  
    # 将predict转换为y_test的数据类型
  97.  
    predict = tf.cast(predict, dtype=y_test.dtype)
  98.  
    # 若分类正确,则correct=1,否则为0,将bool型的结果转换为int型
  99.  
    correct = tf.cast(tf.equal(predict, y_test), dtype=tf.int32)
  100.  
    # 将每个batch的correct数加起来
  101.  
    correct = tf.reduce_sum(correct)
  102.  
    # 将所有batch中的correct数加起来
  103.  
    total_correct = int(correct)
  104.  
    # total_number为测试的总样本数,也就是x_test的行数,shape[0]返回变量的行数
  105.  
    total_number = x_test.shape[0]
  106.  
    # 总的准确率等于total_correct/total_number
  107.  
    acc = total_correct / total_number
  108.  
    print("测试准确率 = %.2f %%" % (acc * 100.0))
  109.  
    data_pre = IsNulldf
  110.  
    x_pre = data_pre.iloc[0:, 1:17] # 取16个特征变量
  111.  
    x_pre = tf.convert_to_tensor(x_pre)#转换为张量
  112.  
    x_pre = tf.cast(x_pre, tf.float32)#转换数据类型
  113.  
    y = tf.matmul(x_pre, w1) b1#y值
  114.  
    y = tf.nn.softmax(y)
  115.  
    category = {0: "性平", 1: "性凉寒", 2: "性温热"}#映射
  116.  
    predict = np.array(tf.argmax(y, axis=1)) # 返回y中最大值的索引,即预测的分类[0]
  117.  
    for i in range(len(predict)):#未知数据预测
  118.  
    print("食物属性为:", category.get(predict[i]))
  119.  
     
  120.  
    #数据标注并写入excel表中
  121.  
    _1index=[]
  122.  
    _2index=[]
  123.  
    _3index = []
  124.  
    for i in range(len(predict)):
  125.  
    if predict[i]== 1:
  126.  
    _1index.append(i)#找到预测为性凉寒
  127.  
    elif predict[i]== 2:
  128.  
    _2index.append(i)#找到温热
  129.  
    else:
  130.  
    _3index.append(i)#找到性平
  131.  
     
  132.  
    #在原始数据中标注好分类
  133.  
    df3['catef'][kongindex[_1index]] = '性凉寒'
  134.  
    df3['catef'][kongindex[_2index]] = '性温热'
  135.  
    df3['catef'][kongindex[_3index]] = '性平'
  136.  
    print(len(_1index),len(_2index),len(_3index))#看预测各类各有多少个
  137.  
     
  138.  
    #将预测分类写入表格
  139.  
    df3_w=pd.concat([df1[df1.columns[0]],df1[df1.columns[2:17]], df3['catef']], axis=1)
  140.  
    writer1 = pd.ExcelWriter('df3.xlsx') # 创建excel表格
  141.  
    df3_w.to_excel(writer1, 'page_1')
  142.  
    writer1.save()#保存
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgjgkfh
系列文章
更多 icon
同类精品
更多 icon
继续加载