本文源自中国慕课网曹健老师《人工智能实践:Tensorflow笔记》一课听课笔记,课程地址:https://www.icourse163.org/learn/PKU-1002536002?tid=1452937471#/learn/content?type=detail&id=1229870565&sm=1
损失函数(loss):预测值(y)与已知答案(y_)的差距。
均方误差mse:
loss_mse=tf.reduce_mean(tf.square(y_-y))
预测酸奶日销量y,x1、x2是影响日销量的因素。
建模前,应预先采集的数据有:每日x1、x2 和销量y_(即已知答案,最佳情况:产量=销量),拟造数据集X,Y_:y_=x1+x2 噪声:-0.05——+0.05 拟合可以预测销量的函数。
import tensorflow as tf
import numpy as np
SEED = 23455
rdm = np.random.RandomState(seed=SEED) # 生成[0,1)之间的随机数
x = rdm.rand(32, 2) #生成的随机数为32行,2列矩阵
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x] # 生成噪声[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05) #标准答案
x = tf.cast(x, dtype=tf.float32) #转换类型
w1 = tf.Variable(tf.random.normal([2, 1], stddev=1, seed=1)) #初始权重设为 均值为0.5,方差为1的2行1列正态分布随机数
epoch = 15000 #循环次数设为15000
lr = 0.002 #初始学习率设为0.002
for epoch in range(epoch):
with tf.GradientTape() as tape:
y = tf.matmul(x, w1) #矩阵相乘,即预测结果y=w1*x1+w2*x2
loss_mse = tf.reduce_mean(tf.square(y_ - y)) #损失函数(均方误差)
grads = tape.gradient(loss_mse, w1) #求梯度,即损失函数下降最快的反向
w1.assign_sub(lr * grads) #更新权值w1,即w1=w1-lr*grads
if epoch % 500 == 0:
print("After %d training steps,w1 is " % (epoch))
print(w1.numpy(), "\n")
print("Final w1 is: ", w1.numpy())
#程序运行结果:
After 0 training steps,w1 is
[[-0.8096241]
[ 1.4855157]]
After 500 training steps,w1 is
[[-0.21934733]
[ 1.6984866 ]]
........
After 14500 training steps,w1 is
[[1.0002553 ]
[0.99838644]]
Final w1 is: [[1.0009792]
[0.9977485]]
可以看到,最后的结果还是比较拟合y_=x1+x2
自定义损失函数:
如预测商品销量,预测多了,损失成本;预测少了,损失利润。
若利润≠成本,则mse产生的loss无法利益最大化。
自定义损失函数:y_数据集的标准答案 y计算出的预测答案。
loss_zdy=tf.reduce_sum(tf.where(tf.greater(y,y_),(y-y_)*cost,(y_-y)*profit))
如:预测酸奶销量,酸奶成本(cost)1元,酸奶利润(profit)99元。
预测少了损失利润99元,大于预测多了损失成本1元。预测少了损失大,希望生成的预测函数往多了预测。
import tensorflow as tf
import numpy as np
SEED = 23455
COST = 1
PROFIT = 99
rdm = np.random.RandomState(SEED)
x = rdm.rand(32, 2) #生成的随机数为32行,2列矩阵
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x] # 生成噪声[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05)
x = tf.cast(x, dtype=tf.float32) #转换数据类型
w1 = tf.Variable(tf.random.normal([2, 1], stddev=1, seed=1)) ##初始权重设为 均值为0.5,方差为1的2行1列正态分布随机数
epoch = 10000
lr = 0.002
for epoch in range(epoch):
with tf.GradientTape() as tape:
y = tf.matmul(x, w1)
loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_) * COST, (y_ - y) * PROFIT)) #自定义损失函数
grads = tape.gradient(loss, w1)
w1.assign_sub(lr * grads)
if epoch % 500 == 0:
print("After %d training steps,w1 is " % (epoch))
print(w1.numpy(), "\n")
print("Final w1 is: ", w1.numpy())
# 自定义损失函数
# 酸奶成本1元, 酸奶利润99元
# 成本很低,利润很高,人们希望多预测些,生成模型系数大于1,往多了预测
#程序运行结果:
After 0 training steps,w1 is
[[2.0855923]
[3.8476257]]
After 500 training steps,w1 is
[[1.1830753]
[1.1627482]]
After 1000 training steps,w1 is
[[1.1526372]
[1.0175619]]
...........
After 9500 training steps,w1 is
[[1.1611756]
[1.0651482]]
Final w1 is: [[1.1626335]
[1.1191947]]
酸奶成本1元, 酸奶利润99元,可想而知,这种情况预测销量是偏大的。
但若酸奶成本99元, 酸奶利润1元呢?
After 9500 training steps,w1 is
[[0.8998995 ]
[0.82509875]]
Final w1 is: [[0.9205433]
[0.9186459]]
可以看到,预测的销量是偏小的。
交叉熵:
交叉熵损失函数CE(Cross Entropy):表征两个概率分布之间的距离。
tf.losses.categorical_crossentropy(y_,y)
eg.二分类 已知答案y_=(1,0) 预测y1=(0.6,0.4) y2=(0.8,0.2)
哪个更接近标准答案?
H1((1,0),(0.6,0.4))=-(1ln0.6+0ln0.4)≈-(-0.511+0)=0.511
H2((1,0),(0.8,0.2))=-(1ln0.8+0ln0.2)≈-(-0.223+0)=0.223
因为H1>H2,所以y2预测更准。
softmax与交叉熵结合:
输出先过softmax函数,在计算y与y_的交叉熵损失函数。
tf.nn.softmax_cross_entropy_with_logits(y_,y)
当我们处理多分类任务时,通常需要使用Softmax Regression模型。即使是卷积神经网络或循环神经网络,如果是分类模型,最后一层也是Softmax Regression。它的基本原理是,将可以判定为某类的特征相加,然后将这些特征转化为判定是这一类的概率。
y_ = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0]])
y = np.array([[12, 3, 2], [3, 10, 1], [1, 2, 5], [4, 6.5, 1.2], [3, 6, 1]])
y_pro = tf.nn.softmax(y)
loss_ce1 = tf.losses.categorical_crossentropy(y_,y_pro)
loss_ce2 = tf.nn.softmax_cross_entropy_with_logits(y_, y)
print('分步计算的结果:\n', loss_ce1)
print('结合计算的结果:\n', loss_ce2)
#程序运行结果:
分步计算的结果:
tf.Tensor(
[1.68795487e-04 1.03475622e-03 6.58839038e-02 2.58349207e+00
5.49852354e-02], shape=(5,), dtype=float64)
结合计算的结果:
tf.Tensor(
[1.68795487e-04 1.03475622e-03 6.58839038e-02 2.58349207e+00
5.49852354e-02], shape=(5,), dtype=float64)
以上内容,如有错误,敬请批评指正!谢谢!