在預(yù)測(cè)商品銷量時(shí),如果預(yù)測(cè)多了(預(yù)測(cè)值比真實(shí)銷量大),商家損失的是生產(chǎn)商品的成本;而如果預(yù)測(cè)少了(預(yù)測(cè)值比真實(shí)銷量小),損失的則是商品的利潤(rùn)。因?yàn)橐话闵唐返某杀竞蜕唐返睦麧?rùn)不會(huì)嚴(yán)格相等,比如如果一個(gè)商品的成本是1元,但是利潤(rùn)是10元,那么少預(yù)測(cè)一個(gè)就少掙10元;而多預(yù)測(cè)一個(gè)才少掙1元,所以如果神經(jīng)網(wǎng)絡(luò)模型最小化的是均方誤差損失函數(shù),那么很有可能此模型就無法最大化預(yù)期的銷售利潤(rùn)。
為了最大化預(yù)期利潤(rùn),需要將損失函數(shù)和利潤(rùn)直接聯(lián)系起來,需要注意的是,損失函數(shù)定義的是損失,所以要將利潤(rùn)最大化,定義的損失函數(shù)應(yīng)該刻畫成本或者代價(jià),下面的公式給出了一個(gè)當(dāng)預(yù)測(cè)多于真實(shí)值和預(yù)測(cè)少于真實(shí)值時(shí)有不同損失系數(shù)的損失函數(shù):
其中,yi為一個(gè)batch中第i個(gè)數(shù)據(jù)的真實(shí)值,yi'為神經(jīng)網(wǎng)絡(luò)得到的預(yù)測(cè)值,a和b是常量,比如在上面介紹的銷量預(yù)測(cè)問題中,a就等于10 (真實(shí)值多于預(yù)測(cè)值的代價(jià)),而b等于1 (真實(shí)值少于預(yù)測(cè)值的代價(jià))。
通過對(duì)這個(gè)自定義損失函數(shù)的優(yōu)化,模型提供的預(yù)測(cè)值更有可能最大化收益,在TensorFlow中,可以通過以下代碼來實(shí)現(xiàn)這個(gè)損失函數(shù):
loss = tf.reduce_sum(tf.where(tf.greater(y_, y), (y_ - y) * loss_less, (y - y_) * loss_more))
①tf.greater函數(shù)的輸入是兩個(gè)張量,此函數(shù)會(huì)比較這兩個(gè)輸入張量中每一個(gè)元素的大小,并返回比較結(jié)果,當(dāng)tf.greater的輸入張量維度不一樣時(shí),TensorFlow會(huì)進(jìn)行類似NumPy廣播操作(broadcasting)的處理;
②tf.where函數(shù)有三個(gè)參數(shù),第一個(gè)為選擇條件,當(dāng)選擇條件為True時(shí),tf.where函數(shù)會(huì)選擇第二個(gè)參數(shù)中的值,否則使用第三個(gè)參數(shù)中的值,需要注意的是,tf.where函數(shù)的判斷和選擇都是在元素級(jí)別進(jìn)行的。
接下來使用一段TensorFlow代碼展示這兩個(gè)函數(shù)的使用:
import tensorflow as tfv1 = 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.]'''
在了解如何使用這兩個(gè)函數(shù)之后,我們來看一看剛才的預(yù)測(cè)商品銷售量的實(shí)例如何通過具體的TensorFlow代碼實(shí)現(xiàn):
import tensorflow as tffrom numpy.random import RandomState#聲明wl、W2兩個(gè)變量,通過seed參數(shù)設(shè)定了隨機(jī)種子,這樣可以保證每次運(yùn)行得到的結(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)#定義真實(shí)值與預(yù)測(cè)值之間的交叉熵?fù)p失函數(shù),來刻畫真實(shí)值與預(yù)測(cè)值之間的差距l(xiāng)oss_less = 10loss_more = 1loss = 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è)置隨機(jī)數(shù)種子rdm = RandomState(seed=1)#設(shè)置隨機(jī)數(shù)據(jù)集大小dataset_size = 128X = rdm.rand(dataset_size, 2)'''設(shè)置回歸的正確值為兩個(gè)輸入的和加上一個(gè)隨機(jī)量。之所以要加上一個(gè)隨機(jī)量是為了加入不可預(yù)測(cè)的噪音,否則不同損失函數(shù)的意義就不大了,因?yàn)椴煌瑩p失函數(shù)都會(huì)在能完全預(yù)測(cè)正確的時(shí)候最低。一般來說噪音為一個(gè)均值為0的小量,所以這里的噪音設(shè)置為-0.05——0.05的隨機(jī)數(shù)。'''Y = [[x1 + x2 + rdm.rand()/10.0 -0.05] for x1,x2 in X]#創(chuàng)建會(huì)話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個(gè)樣本進(jìn)行訓(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]]'''
新聞熱點(diǎn)
疑難解答
圖片精選