1. 多分类问题
思考一个问题,神经网络输出的结果如何解决分类问题呢?解决多分类问题,一个常用的方法就是:我们主要考虑在logistic后加上Softmax分类映射,输出分类的概率,进而进行分类。
- 从神经网络结构的角度去看,对神经网络设置n个输出节点,其中n就是分类的类别数
- softmax回归:softmax回归可以将神经网络的n个输出节点转换成该分类的发生概率
根据softmax计算公式可以看出,若上一步计算出的结果越大,则经过softmax计算后的结果也越大,说明该事件发生的概率越大。softmax好处是n个输出节点经过softmax计算出的概率,加和等于1(所有事件发生的可能性总和为1)。
1.1 损失函数
回想一下,线性回归的损失函数我们常用均方误差(MSE),逻辑回归的损失函数常用对数似然函数。损失函数是用来后续梯度下降优化的关键,那么多分类问题的损失函数应该用哪一个呢?神经网络常用的衡量损失的方法是交叉熵损失函数。
- 为了衡量距离,目标值需要进行one-hot编码,能与概率值一一对应
TensorFlow中交叉熵损失API:
tf.nn.softmax_cross_entropy_with_logits(labels=None, logits=None, name=None)
- 计算logits和label之间的交叉损失熵
- labels:标签值(真实值)
- logits:样本加权之后的值,线性加权后的输出
- return:返回损失值列表
tf.reduce_mean(input_tensor)
- 计算张量的尺寸的元素平均值
2. 案例演示
Mnist数据集介绍,每一张图片包含2828=784个像素。特征值由2828个元素组成,对于目标值,总共有0-9十个类别。因为是分类问题,使用的是one-hot编码。
接下来,我们考虑使用全连接神经网络进行手写数字识别:
-
全连接神经网路参数变化形式:y=w1x1+w2x2+w3x3+…+wnxny=w1x1+w2x2+w3x3+…+wnxn
-
张量变化形式:x[batch,784]∗w[784,10]+bias=ypredict[batch,10]x[batch, 784] * w[784, 10] + bias = y_predict[batch, 10]
下面将进行案例演示:
2.1 步骤1
- 导入所需模块,因为本地下载的是Tensoflow2.x版本,想要运行Tensorflow1.x版本语法,需要开启兼容模式,禁用2.x版本语法。
- 另外,我们需要通过api直接导入mnist数据,所以,需要额外导入input_data方法。
import tensorflow as tf
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
import os
from tensorflow.examples.tutorials.mnist import input_data
步骤2:
构造函数,进行神经网络搭建及训练,主要分为如下几步:
- 准备数据
- 使用占位符构造x数据与y_true数据
- 构建模型
- 构造weight,bias,y_predict
- 构造参数传递关系过程
- 构造损失函数
- 我们使用交叉熵损失函数,函数内部传入真实值变量与预测值变量
- 优化损失
- 使用梯度下降优化器进行优化损失
- 学习率设置为0.02
- 开启会话
- 开启会话才能查看内部参数,使其运行起来
- 一次批处理大小为100
- 开始训练
- 训练轮数设置为500次
- 接受训练过程中的损失值
def full_connection():
"""
用全连接神经网络识别手写数字
"""
# 1. 准备数据
mnist = input_data.read_data_sets("./mnist_data", one_hot=True)
x = tf.placeholder(dtype=tf.float32, shape=(None, 784)) # 784列:一张图片由784个像素组成,一次传入N张图片
y_true = tf.placeholder(dtype=tf.float32, shape=(None, 10)) # 10列
# 2. 构建模型
weights = tf.Variable(initial_value=tf.random_normal(shape=(784, 10)))
bias = tf.Variable(initial_value=tf.random_normal(shape=[10])) # 10个标量
y_predict = tf.matmul(x, weights) + bias
# 3. 构造损失函数
error = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict)) # 交叉熵损失函数,再求平均值
# 4. 优化损失
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.02).minimize(error) # 梯度下降优化器,最小化损失
# 初始化变量
init = tf.global_variables_initializer()
# 开启会话
with tf.Session() as sess:
sess.run(init)
image, label = mnist.train.next_batch(100)
print("训练之前的损失loss为:%f" % sess.run(error, feed_dict={x:image, y_true:label}))
# 开始训练
for i in range(500):
_, loss = sess.run([optimizer,error], feed_dict={x:image, y_true:label}) # optimizer是一个操作,不需要其返回值,用_(None)来接收
print("第%d次训练,损失为%f" % (i+1, loss))
return None
full_connection()
代码运行结果如下图所示:
- 图中可以看出经过500论训练,损失变为1.16左右。还有下降趋势,可以继续增大训练轮数。
本文正在参加「金石计划 . 瓜分6万现金大奖」