TensorFlow自定義損失函數(shù)來預(yù)測商品銷售量
在預(yù)測商品銷量時,如果預(yù)測多了(預(yù)測值比真實銷量大),商家損失的是生產(chǎn)商品的成本;而如果預(yù)測少了(預(yù)測值比真實銷量?。?,損失的則是商品的利潤。因為一般商品的成本和商品的利潤不會嚴格相等,比如如果一個商品的成本是1元,但是利潤是10元,那么少預(yù)測一個就少掙10元;而多預(yù)測一個才少掙1元,所以如果神經(jīng)網(wǎng)絡(luò)模型最小化的是均方誤差損失函數(shù),那么很有可能此模型就無法最大化預(yù)期的銷售利潤。
為了最大化預(yù)期利潤,需要將損失函數(shù)和利潤直接聯(lián)系起來,需要注意的是,損失函數(shù)定義的是損失,所以要將利潤最大化,定義的損失函數(shù)應(yīng)該刻畫成本或者代價,下面的公式給出了一個當(dāng)預(yù)測多于真實值和預(yù)測少于真實值時有不同損失系數(shù)的損失函數(shù):

其中,yi為一個batch中第i個數(shù)據(jù)的真實值,yi'為神經(jīng)網(wǎng)絡(luò)得到的預(yù)測值,a和b是常量,比如在上面介紹的銷量預(yù)測問題中,a就等于10 (真實值多于預(yù)測值的代價),而b等于1 (真實值少于預(yù)測值的代價)。
通過對這個自定義損失函數(shù)的優(yōu)化,模型提供的預(yù)測值更有可能最大化收益,在TensorFlow中,可以通過以下代碼來實現(xiàn)這個損失函數(shù):
loss = tf.reduce_sum(tf.where(tf.greater(y_, y), (y_ - y) * loss_less, (y - y_) * loss_more))
①tf.greater函數(shù)的輸入是兩個張量,此函數(shù)會比較這兩個輸入張量中每一個元素的大小,并返回比較結(jié)果,當(dāng)tf.greater的輸入張量維度不一樣時,TensorFlow會進行類似NumPy廣播操作(broadcasting)的處理;
②tf.where函數(shù)有三個參數(shù),第一個為選擇條件,當(dāng)選擇條件為True時,tf.where函數(shù)會選擇第二個參數(shù)中的值,否則使用第三個參數(shù)中的值,需要注意的是,tf.where函數(shù)的判斷和選擇都是在元素級別進行的。
接下來使用一段TensorFlow代碼展示這兩個函數(shù)的使用:
import tensorflow as tf v1 = tf.constant([1.0, 2.0, 3.0, 4.0]) v2 = tf.constant([4.0, 3.0, 2.0, 1.0]) with tf.Session() as sess: print(sess.run(tf.greater(v1, v2))) print(sess.run(tf.where(tf.greater(v1, v2), v1, v2))) '''輸出結(jié)果為: [False False True True] [4. 3. 3. 4.]'''
在了解如何使用這兩個函數(shù)之后,我們來看一看剛才的預(yù)測商品銷售量的實例如何通過具體的TensorFlow代碼實現(xiàn):
import tensorflow as tf
from numpy.random import RandomState
#聲明wl、W2兩個變量,通過seed參數(shù)設(shè)定了隨機種子,這樣可以保證每次運行得到的結(jié)果是一樣的
w = tf.Variable(tf.random_normal([2, 1], stddev=1, seed=1))
x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input")
y_ = tf.placeholder(tf.float32, shape=(None, 1), name="y-input")
#定義神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
y = tf.matmul(x, w)
#定義真實值與預(yù)測值之間的交叉熵損失函數(shù),來刻畫真實值與預(yù)測值之間的差距
loss_less = 10
loss_more = 1
loss = tf.reduce_sum(tf.where(tf.greater(y_, y), (y_ - y) * loss_less, (y - y_) * loss_more))
#定義反向傳播算法的優(yōu)化方法
train_step = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
#設(shè)置隨機數(shù)種子
rdm = RandomState(seed=1)
#設(shè)置隨機數(shù)據(jù)集大小
dataset_size = 128
X = rdm.rand(dataset_size, 2)
'''設(shè)置回歸的正確值為兩個輸入的和加上一個隨機量。
之所以要加上一個隨機量是為了加入不可預(yù)測的噪音,否則不同損失函數(shù)的意義就不大了,因為不同損失函數(shù)都會在能完全預(yù)測正確的時候最低。
一般來說噪音為一個均值為0的小量,所以這里的噪音設(shè)置為-0.05——0.05的隨機數(shù)。'''
Y = [[x1 + x2 + rdm.rand()/10.0 -0.05] for x1,x2 in X]
#創(chuàng)建會話
with tf.Session() as sess:
#初始化變量
init_op = tf.global_variables_initializer()
sess.run(init_op)
print(sess.run(w))
#設(shè)置batch訓(xùn)練數(shù)據(jù)的大小
batch_size = 8
#設(shè)置訓(xùn)練得輪數(shù)
STEPS = 5000
for i in range(STEPS):
#每次選取batch_size個樣本進行訓(xùn)練
start = (i * batch_size) % dataset_size
end = min(start + batch_size, dataset_size)
#通過選取的樣本訓(xùn)練神經(jīng)網(wǎng)絡(luò)并更新參數(shù)
sess.run(train_step, feed_dict={x:X[start:end], y_:Y[start:end]})
print(sess.run(w))
'''輸出結(jié)果為:
[[-0.8113182]
[ 1.4845988]]
[[1.019347 ]
[1.0428089]]'''
可以看到參數(shù)w優(yōu)化后,預(yù)測函數(shù)為1.019347 * x1 + 1.0428089 * x2,顯然是大于實際的預(yù)測函數(shù)x1 + x2的,這是因為我們的損失函數(shù)中指定預(yù)測少了的損失更大(loss_less > loss_more),所以模型會偏向于預(yù)測多一點。
如果我們更換代碼,改為:
loss_less = 1 loss_more = 10
那么我們的結(jié)果就會變?yōu)椋?/p>
[[-0.8113182] [ 1.4845988]] [[0.95561105] [0.98101896]]
預(yù)測函數(shù)變?yōu)榱?.95561105 * x1 + 0.98101896 * x2,可以看到這時候模型就會偏向于預(yù)測少一點。
因此,我們可以得出結(jié)論:對于相同的神經(jīng)網(wǎng)絡(luò),不同的損失函數(shù)會對訓(xùn)練得到的模型產(chǎn)生不同效果。
總結(jié)
以上所述是小編給大家介紹的TensorFlow自定義損失函數(shù)來預(yù)測商品銷售量,希望對大家有所幫助!
相關(guān)文章
Python操作dict時避免出現(xiàn)KeyError的幾種解決方法
這篇文章主要介紹了Python操作dict時避免出現(xiàn)KeyError的幾種解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Python編寫一個驗證碼圖片數(shù)據(jù)標(biāo)注GUI程序附源碼
這篇文章主要介紹了Python編寫一個驗證碼圖片數(shù)據(jù)標(biāo)注GUI程序,本文給大家附上小編精心整理的源碼,需要的朋友可以參考下2019-12-12
OpenCV學(xué)習(xí)記錄python實現(xiàn)連通域處理函數(shù)
這篇文章主要為大家介紹了OpenCV學(xué)習(xí)記錄python實現(xiàn)連通域處理函數(shù)cv2.connectedComponentsWithStats()和cv2.connectedComponents()的使用示例詳解2022-06-06
Python RuntimeError: thread.__init__() not called解決方法
這篇文章主要介紹了Python RuntimeError: thread.__init__() not called解決方法,需要的朋友可以參考下2015-04-04
Win7上搭建Cocos2d-x 3.1.1開發(fā)環(huán)境
現(xiàn)在,越來越多的公司采用Cocos2d-x 3.0來開發(fā)游戲了,但是現(xiàn)在這樣的文章并不多,所以打算寫一系列來幫助初學(xué)者快速掌握Cocos2d-x 3.0。首先就從開發(fā)環(huán)境的大家說起吧2014-07-07
Python3正則表達式之:(?(id/name)yes-pattern|no-pattern)條件性匹配
(?(id/name)yes-pattern|no-pattern)的作用是對于給出的id或者name,先嘗試去匹配 yes-pattern部分的內(nèi)容,如果id或name條件不滿足,則去匹配no-pattern部分的內(nèi)容2021-10-10

