小白的机器学习笔记系列 之七 - 简单的BP神经网络实例

继续上一课的神经网络的话题,这次我们来实践一个简单的BP神经网络分类任务。

数据集介绍

首先,来认识一下任务所需的数据集 - voice gender dataset。
这个数据集是用于通过声音的一些属性来鉴别声音的性别。数据集包含了3168条数据记录, 分别来自男性或女性的声音属性。数据集格式是csv格式。声音的属性包括平均频率频率的表方差频率的中位数等20项声音属性,皆为float类型数据。每条记录还标识了性别,male(男),female(女)。我们将其中2640作为训练集, 剩下528条作为测试数据。
该数据下载链接
https://download.csdn.net/download/deecheanW/12302204

网络结构设计

这个数据分类任务,如果使用逻辑回归的话,准确率大约可以达到91%左右。1
逻辑回归的代码可以参照下文中的例子稍作修改即可。
https://blog.csdn.net/deecheanW/article/details/82927922

此处,我们来搭建一个2层的神经网络分类器,来实现分类任务。网络结构示意图如下图。

  • 输入层: 20个输入参数分布
  • **隐藏层:**第一层隐藏层为全连接层,有17个节点,第二层隐藏层依旧是全连接层,2个节点。
  • 输出层: 使用softmax归一化,2个节点的参数转换成概率值。
    在这里插入图片描述

代码实现

1. 构建网络

#定义输入参数的placehoder 
with tf.name_scope('input'):
    x = tf.placeholder(tf.float32, [None, 20])
    y_ = tf.placeholder(tf.int64, [None])

#构建第一层隐藏层,输入20个参数,输出17个参数,使用tanh作为激活函数          
with tf.name_scope('hidden_layer_1'):
    W_1 = tf.Variable(tf.random_uniform([20,17]))
    b_1 = tf.Variable(tf.zeros([17]))
    node_1 = tf.nn.tanh(tf.matmul(x,W_1)+b_1)
    print(node_1.shape)
#构建第二层隐藏层,输入17个参数,输出2个参数,最后使用softmax归一化获得输出结果
with tf.name_scope('output'):
    W_2 = tf.Variable(tf.random_uniform([17,2]))
    b_2 = tf.Variable(tf.zeros([2]))
    y = tf.nn.softmax(tf.matmul(node_1,W_2)+b_2)

构建损失函数,使用tensorflow函数sparse_softmax_cross_entropy_with_logits来获得交叉熵。
此处,参数logits是softmax输出结果,labels则是标签值,这里的标签值不需要做成onehot形式,但需要确保表格中可能出现的值得个数和softmax的输出维度一直。比如,此处我们标签就只有0和1两个可能的值,所以softmax的输出维度为2。

with tf.name_scope('loss'):
    loss =  tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=y_,name="cross_entropy_per_example"))

定义训练,此处推荐使用AdagradOptimizer,这是一个自适应学习率的学习优化器,我们给出的学习率(learn rate)仅是一个初始值,在参数更新过程中,实际的学习率是会根据loss的速度进行调整。

with tf.name_scope('train_step'):
    train_step = tf.train.AdagradOptimizer(LEARN_RATE).minimize(loss)   

最后,我们定义准确率,以便衡量训练效果。tf.argmax函数可以获得张量某一维度上最大值得位子索引,这就是我们的预测结果了。然后,我们将预测结果和标签比较,计算正确率。tf.equal用于比较两个tensor是否相等,如相等则返回一,即预测成功,如不相等则预测失败,由此获得一个只有0,1的一维向量。tf.reduce_mean对该向量求平均值,获得预测准确率。

with tf.name_scope('accuracy'):
    prediction =tf.argmax(y, 1)
    accuracy = tf.reduce_mean(tf.cast(tf.equal(prediction,y_), tf.float32))

2. 训练模型

以下是模型训练的完整代码。
首先,定义参数初始化运算 init 和模型保存对象 saver。

然后,启动一个Session来进行训练。tf.get_default_graph().finalize()是用来锁定算图,后面任何代码试图改变算图都会报错,这样可以帮助我们养成良好代码习惯,提高运算速度。

我们进行100000次的迭代训练,每次迭代首先获得训练数据集,然后调用session的run方法来启动之前定义的训练对象 train_step。同时,我们还加入了accuracy, loss的运算,方便我们查看训练效果。每1000次迭代,输出一次训练准确度。大约在接近100000次迭代左右,就可以比较稳定的获得98%的准确率。

训练完成后,保存模型到之前预定义的目录下。

import time
#载入训练数据集, mini-batch的size是1000
train_data = voicegender_data('./voicegender_data/voicegender_train.csv', batch_size=1000)

#参数初始化
init = tf.global_variables_initializer()
#定义一个saver对象用于保存训练后的模型  
saver = tf.train.Saver(max_to_keep=1)

with tf.Session() as sess:      
    sess.run(init)
    tf.get_default_graph().finalize()
    for j in range(100000):
        input_data, train_label = train_data.get_batch_data()
        accuracy_val, loss_val, _ = sess.run([accuracy, loss, train_step], 
                         feed_dict={x: input_data, y_: train_label})
        #每1000次迭代,输出一次训练准确度
        if (j+1) % 1000 == 0:
            print('Step %d: loss = %.2f, accuracy = %.2f'%(j,loss_val,accuracy_val))
#训练完成,保存模型参数    
	saver.save(sess,ckpt_dir+'simpl_nn_ckpt',global_step=j+1)
    print("Training is done.")

3. 测试模型

先载入测试数据集, 然后启动一个Session, saver对象将从之前保存的训练参数载入,启动run来获得accuracy和loss。这里因为不需要训练,所以run时不要放入train_step对象,就不会更新训练的参数。

test_data = voicegender_data('./voicegender_data/voicegender_test.csv', batch_size=1000)

with tf.Session() as sess:      
    sess.run(init)
    model_file=tf.train.latest_checkpoint(ckpt_dir)
    saver.restore(sess,model_file)
    accuracy_val, loss_val = sess.run([accuracy, loss], 
                         feed_dict={x: test_data.data_list, y_: test_data.label_list})
    print('Test result: loss = %.2f, accuracy = %.2f'%(loss_val,accuracy_val))

源码下载链接
https://download.csdn.net/download/deecheanW/12302445


  1. 参照该数据集的说明,逻辑回归的分类准确度可达98%。 ↩︎

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小白的逆袭日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值