自定義損失函數


自定義損失函數:根據問題的實際情況,定制合理的損失函數。
例如:

對於預測酸奶日銷量問題,如果預測銷量大於實際銷量則會損失成本;如果預測銷量小於實際銷量則會損失利潤。在實際生活中,往往制造一盒酸奶的成本和銷售一盒酸奶的利潤是不等價的。因此,需要使用符合該問題的自定義損失函數。 

自定義損失函數為:loss = ∑𝑛𝑓(y_,y)
其中,損失定義成分段函數:

 

損失函數表示,若預測結果 y 小於標准答案 y_,損失函數為利潤乘以預測結果 y 與標准答案 y_之差;
若預測結果 y 大於標准答案 y_,損失函數為成本乘以預測結果 y 與標准答案 y_之差。
用 Tensorflow 函數表示為: loss = tf.reduce_sum(tf.where(tf.greater(y,y_),COST(y-y_),PROFIT(y_-y)))

① 若酸奶成本為 1 元,酸奶銷售利潤為 9 元,則制造成本小於酸奶利潤,因此希望預測的結果 y 多一些。采用上述的自定義損失函數,訓練神經網絡模型

y=w1*x1+w2*x2;若成本低於利潤,則應該y稍稍大於標准值。

標准值是:y_=x1+x2;

 代碼:

#coding:utf-8
#tensorflow學習筆記(北京大學) 
#酸奶成本1元, 酸奶利潤9元
#預測少了損失大,故不要預測少,故生成的模型會多預測一些
#0導入模塊,生成數據集
import tensorflow as tf
import numpy as np
BATCH_SIZE = 8
SEED = 23455#隨機種子
COST = 1#花費
PROFIT = 9#成本

rdm = np.random.RandomState(SEED)#基於seed產生隨機數
X = rdm.rand(32,2)#隨機數返回32行2列的矩陣 表示32組 體積和重量 作為輸入數據集
Y = [[x1+x2+(rdm.rand()/10.0-0.05)] for (x1, x2) in X]

#1定義神經網絡的輸入、參數和輸出,定義前向傳播過程。
x = tf.placeholder(tf.float32, shape=(None, 2))#占位
y_ = tf.placeholder(tf.float32, shape=(None, 1))#占位
w1= tf.Variable(tf.random_normal([2, 1], stddev=1, seed=1))#正態分布
y = tf.matmul(x, w1)#點積

#2定義損失函數及反向傳播方法。
# 定義損失函數使得預測少了的損失大,於是模型應該偏向多的方向預測。
#tf.where:如果condition對應位置值為True那么返回Tensor對應位置為x的值,否則為y的值.
#where(condition, x=None, y=None,name=None)
loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_)*COST, (y_ - y)*PROFIT))
train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss)#隨機梯度下降

#3生成會話,訓練STEPS輪。
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()#初始化
    sess.run(init_op)#初始化
    STEPS = 3000
    for i in range(STEPS):#三千輪
        start = (i*BATCH_SIZE) % 32  #8個數據  為一個數據塊輸出
        end = (i*BATCH_SIZE) % 32 + BATCH_SIZE  #[i:i+8]
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})#訓練
        if i % 500 == 0:#每500輪打印輸出
            print "After %d training steps, w1 is: " % (i)#打印i
            print sess.run(w1), "\n"#打印w1
    print "Final w1 is: \n", sess.run(w1)#最終打印w1

②若酸奶成本為 9 元,酸奶銷售利潤為 1 元,則制造成本大於酸奶利潤,因此希望預測結果 y 小一些。采用上述的自定義損失函數,訓練神經網絡模型。

同理,成本大於利潤,則希望y相對小一些

代碼:

#coding:utf-8
#酸奶成本9元, 酸奶利潤1元
#預測多了損失大,故不要預測多,故生成的模型會少預測一些
#0導入模塊,生成數據集
import tensorflow as tf
import numpy as np
BATCH_SIZE = 8
SEED = 23455
COST = 9
PROFIT = 1

rdm = np.random.RandomState(SEED)
X = rdm.rand(32,2)
Y = [[x1+x2+(rdm.rand()/10.0-0.05)] for (x1, x2) in X]

#1定義神經網絡的輸入、參數和輸出,定義前向傳播過程。
x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))
w1= tf.Variable(tf.random_normal([2, 1], stddev=1, seed=1))
y = tf.matmul(x, w1)

#2定義損失函數及反向傳播方法。
#重新定義損失函數,使得預測多了的損失大,於是模型應該偏向少的方向預測。
loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_)*COST, (y_ - y)*PROFIT))
train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss)

#3生成會話,訓練STEPS輪。
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    STEPS = 3000
    for i in range(STEPS):
        start = (i*BATCH_SIZE) % 32
        end = (i*BATCH_SIZE) % 32 + BATCH_SIZE
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})
        if i % 500 == 0:
            print "After %d training steps, w1 is: " % (i)
            print sess.run(w1), "\n"
    print "Final w1 is: \n", sess.run(w1)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM