tensorflow05——关于帮助理解【损失函数】的一个实例

酸奶日销量y(预测值) x1,x2是两个影响日销量的因素
【现在需要探讨y与x1和x2的关系】
损失函数:使用mse-均方误差损失函数
tf表达式为:lose_mse=tf.reduce_mean(tf.square(y_-y))
(y_真实值,y预测值),损失函数就是计算真实值与预测值之间的距离,所以越小越好

建模前应当预先采集的数据有
每日的x1,x2和当日真实销量y_(真实值)

【数据集准备】
为了方便实验
随机自动生成一个包含两个因素x1,x2的数据集x(x越大越好)
和一个表示真实销量的数据集y_
我们暂且拟定y_=x1+x2(也就是两个因素的系数都为1,同样重要)
为了更接近真实情况,再架上一个随机噪声(-0.05~+0.05)

已知答案——最佳情况是: 产量=销量
(生产多了会赔钱,生产少了少挣钱)

import tensorflow as tf
import numpy as np

SEED=23455

#rdm函数,指定随机种子23455————生成[0,1)之间的随机数
rdm=np.random.RandomState(seed=SEED)

# 生成包含两个因素x1和x2的随机数据集x(32组)——32*2
# 生成表示真实销量的随机数据集y_(32*1)
# 暂定(y_=x1+x2+随机噪声)
x=rdm.rand(32,2)
y_=[[x1+x2+(rdm.rand()/10.0-0.05) ] for (x1,x2) in x]
x=tf.cast(x,dtype=tf.float32)

#随机初始化可更新的变量w1,2*1
w1=tf.Variable(tf.random.normal([2,1],stddev=1,seed=1)) 

epoch=10000
lr=0.002

for epoch in range(epoch):
    with tf.GradientTape() as tape:
        #计算预测值
        y=tf.matmul(x,w1)
        #计算均方误差
        loss_mse=tf.reduce_mean(tf.square(y_-y))

        
    #梯度更新参数
    grads=tape.gradient(loss_mse,w1)
    w1.assign_sub(lr*grads)    
    
    #每训练500轮输出一次w1两个参数
    if epoch%500==0:
        print("经过%d轮训练,w1的值为"%(epoch))
        print(w1.numpy(),"\n")

print("最终w1的值为",w1.numpy())

以上用均方误差作为损失函数,默认是认为销量预测多了或者少了,损失是一样的,所以从头到尾这个loss函数都没有变化。然而真实情况是,预测多了,会损失成本COST,预测少了,会损失利润PROFIT,而利润和成本往往不相等,这种情况下使用均方误差计算loss,无法达到利益最大化。

自定义损失函数

将loss函数定义为一个分段函数
每一轮比较预测值和真实值决定loss值

当预测值y小于真实值y_的时候,预测少了,损失利润
得出一个损失值PROFIT(y_ - y)
当预测值y大于等于真实值y_的时候,预测多了,损失成本
得出一个损失值COST(y - y_)
最后将所有损失值求和

实现:就是一个条件判断的三段式,前面加一个sum求和

loss_zdy=tf.reduce_sum(tf.where(tf.greater(y,y_),COST*(y-y_),PROFIT*(y_-y))

假设酸奶成本1元,酸奶利润99元
预测少了损失利润99元,预测多了损失成本1元
预测少了损失更大,所以希望模型,也就是最终预测的函数
尽量往销量多的方向预测

import tensorflow as tf
import numpy as np

SEED=23455
COST=1
PROFIT=99

#重命名函数rdm——生成[0,1)之间的随机数
rdm=np.random.RandomState(seed=SEED)

#生成包含两个因素x1和x2的随机数据集x(32组)
#生成表示真实销量的随机数据集y_
#(y_=x1+x2+随机噪声)

x=rdm.rand(32,2)
y_=[[x1+x2+(rdm.rand()/10.0-0.05) ] for (x1,x2) in x]

x=tf.cast(x,dtype=tf.float32)

#随机初始化可更新的变量w1,两行一列
w1=tf.Variable(tf.random.normal([2,1],stddev=1,seed=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)    
    
    #每训练20轮输出一次w1两个参数
    if epoch%500==0:
        print("经过%d轮训练,w1的值为"%(epoch))
        print(w1.numpy(),"\n")

print("最终w1的值为",w1.numpy())


        

你可能感兴趣的:(tensorflow,深度学习,python,tensorflow)