1. 程式人生 > 程式設計 >TensorFlow自定義損失函式來預測商品銷售量

TensorFlow自定義損失函式來預測商品銷售量

在預測商品銷量時,如果預測多了(預測值比真實銷量大),商家損失的是生產商品的成本;而如果預測少了(預測值比真實銷量小),損失的則是商品的利潤。因為一般商品的成本和商品的利潤不會嚴格相等,比如如果一個商品的成本是1元,但是利潤是10元,那麼少預測一個就少掙10元;而多預測一個才少掙1元,所以如果神經網路模型最小化的是均方誤差損失函式,那麼很有可能此模型就無法最大化預期的銷售利潤。

為了最大化預期利潤,需要將損失函式和利潤直接聯絡起來,需要注意的是,損失函式定義的是損失,所以要將利潤最大化,定義的損失函式應該刻畫成本或者代價,下面的公式給出了一個當預測多於真實值和預測少於真實值時有不同損失係數的損失函式:

TensorFlow自定義損失函式來預測商品銷售量

其中,yi為一個batch中第i個數據的真實值,yi'為神經網路得到的預測值,a和b是常量,比如在上面介紹的銷量預測問題中,a就等於10 (真實值多於預測值的代價),而b等於1 (真實值少於預測值的代價)。

通過對這個自定義損失函式的優化,模型提供的預測值更有可能最大化收益,在TensorFlow中,可以通過以下程式碼來實現這個損失函式:

loss = tf.reduce_sum(tf.where(tf.greater(y_,y),(y_ - y) * loss_less,(y - y_) * loss_more))

①tf.greater函式的輸入是兩個張量,此函式會比較這兩個輸入張量中每一個元素的大小,並返回比較結果,當tf.greater的輸入張量維度不一樣時,TensorFlow會進行類似NumPy廣播操作(broadcasting)的處理;

②tf.where函式有三個引數,第一個為選擇條件,當選擇條件為True時,tf.where函式會選擇第二個引數中的值,否則使用第三個引數中的值,需要注意的是,tf.where函式的判斷和選擇都是在元素級別進行的。

接下來使用一段TensorFlow程式碼展示這兩個函式的使用:

import tensorflow as tf
v1 = tf.constant([1.0,2.0,3.0,4.0])
v2 = tf.constant([4.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)))
 '''輸出結果為:
 [False False True True]
 [4. 3. 3. 4.]'''

在瞭解如何使用這兩個函式之後,我們來看一看剛才的預測商品銷售量的例項如何通過具體的TensorFlow程式碼實現:

import tensorflow as tf
from numpy.random import RandomState

#宣告wl、W2兩個變數,通過seed引數設定了隨機種子,這樣可以保證每次執行得到的結果是一樣的
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,1),name="y-input")

#定義神經網路結構
y = tf.matmul(x,w)

#定義真實值與預測值之間的交叉熵損失函式,來刻畫真實值與預測值之間的差距
loss_less = 10
loss_more = 1
loss = tf.reduce_sum(tf.where(tf.greater(y_,(y - y_) * loss_more))

#定義反向傳播演算法的優化方法
train_step = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)

#設定隨機數種子
rdm = RandomState(seed=1)
#設定隨機資料集大小
dataset_size = 128
X = rdm.rand(dataset_size,2)
'''設定迴歸的正確值為兩個輸入的和加上一個隨機量。
之所以要加上一個隨機量是為了加入不可預測的噪音,否則不同損失函式的意義就不大了,因為不同損失函式都會在能完全預測正確的時候最低。
一般來說噪音為一個均值為0的小量,所以這裡的噪音設定為-0.05——0.05的隨機數。'''
Y = [[x1 + x2 + rdm.rand()/10.0 -0.05] for x1,x2 in X]

#建立會話
with tf.Session() as sess:
 #初始化變數
 init_op = tf.global_variables_initializer()
 sess.run(init_op)
 
 print(sess.run(w))
 
 #設定batch訓練資料的大小
 batch_size = 8
 #設定訓練得輪數
 STEPS = 5000
 for i in range(STEPS):
  #每次選取batch_size個樣本進行訓練
  start = (i * batch_size) % dataset_size
  end = min(start + batch_size,dataset_size)

  #通過選取的樣本訓練神經網路並更新引數
  sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})
 
 print(sess.run(w))
 '''輸出結果為:
 [[-0.8113182]
 [ 1.4845988]]
 [[1.019347 ]
 [1.0428089]]'''

可以看到引數w優化後,預測函式為1.019347 * x1 + 1.0428089 * x2,顯然是大於實際的預測函式x1 + x2的,這是因為我們的損失函式中指定預測少了的損失更大(loss_less > loss_more),所以模型會偏向於預測多一點。

如果我們更換程式碼,改為:

loss_less = 1
loss_more = 10

那麼我們的結果就會變為:

[[-0.8113182]
 [ 1.4845988]]
[[0.95561105]
 [0.98101896]]

預測函式變為了0.95561105 * x1 + 0.98101896 * x2,可以看到這時候模型就會偏向於預測少一點。

因此,我們可以得出結論:對於相同的神經網路,不同的損失函式會對訓練得到的模型產生不同效果。

總結

以上所述是小編給大家介紹的TensorFlow自定義損失函式來預測商品銷售量,希望對大家有所幫助!