TensorFlow上實踐基於自編碼的One Class Learning


我不知道什么是愛,但我知道什么是不愛” 

--One Class Learning的自白

 一、單分類簡介

  如果將分類算法進行划分,根據類別個數的不同可以分為單分類、二分類、多分類,常見的分類算法主要解決二分類和多分類問題,預測一封郵件是否是垃圾郵件是一個典型的二分類問題,手寫體識別是一個典型的多分類問題,這些算法並不能很好的應用在單分類上,但單分類問題在工業界廣泛存在,由於每個企業刻畫用戶的數據都是有限的,很多二分類問題很難找到負樣本,比如通過用戶的搜索記錄預測一個用戶是否有小孩,可以通過規則篩選出正樣本,如經常搜索“寶寶、早教”之類的詞,但很難篩選出合適的負樣本,一個用戶沒有搜索並不代表沒有小孩,即便用一些排除法篩選出負樣本,負樣本也會不純,不能保證負樣本中沒有正樣本,這樣用分類模型跑出的結果存在解釋性的困難,預測概率高可以認為是有很有可能有小孩,但概率低是有小孩的的可能小還是無法判斷?在只能定義正樣本不能定義負樣本的場景中,使用單分類算法(One-Class Learning)更適合,單分類算法只關注與樣本的相似或匹配程度,對於未知的部分不妄下結論。很多人會說“我不知道什么是愛,但我知道什么是不愛”,他們相親時會立馬排查掉不愛的對象,他們就是一個聰明的One-Class學習器。

  當然分類算法根據記錄所屬類別個數的不同還可以分為單標簽分類和多標簽分類,預測一個用戶喜歡的球類就是一個多標簽多分類問題,這里不多加討論,本文重點討論單分類問題。

 

 

二、單分類算法介紹

  One Class Learning比較經典的算法是One-Class-SVM[參考文獻1],這個算法的思路非常簡單,就是尋求一個超平面將樣本中的正例圈起來,預測是就用這個超平面做決策,在圈內的樣本就認為是正樣本。由於核函數計算比較耗時,在海量數據的場景用得並不多;

one class svm示例圖(圖片引用自[參考文獻2])

  

   另外一個算法是基於神經網絡的算法,在深度學習中廣泛使用的自編碼算法可以應用在單分類的問題上[參考文獻3],自編碼器是一個BP神經網絡,網絡輸入層和輸出層是一樣,中間層數可以有多層,中間層的節點個數比輸出入層少,最簡單的情況就是中間只有一個隱藏層,如下圖所示,由於中間層的節點數較少,這樣中間層相當於是對數據進行了壓縮和抽象,實現無監督的方式學習數據的抽象特征。

  如果我們只有正樣本數據,沒有負樣本數據,或者說只關注學習正樣本的規律,那么利用正樣本訓練一個自編碼器,編碼器就相當於單分類的模型,對全量數據進行預測時,通過比較輸入層和輸出層的相似度就可以判斷記錄是否屬於正樣本。由於自編器采用神經網絡實現,可以用GPU來進行加速計算,因此比較適合海量數據的場景。

三、單分類算法實踐 

  這里使用TensorFlow實踐了一下基於自編碼的One-Class-Learning,代碼引用自[參考文獻4],使用MNIST數據進行自編碼,首先用0-9這10個類別的數據進行訓練,輸入層和輸出層節點數為784,中間層有兩層,節點數分別為256、128,下圖中第一排是原始圖片,第二排是自編碼后解碼的圖片,可以認為第二排圖片是128個單元節點的壓縮表示。

  假設現在是一個單分類問題,我們只有部分數字7的標注數據,現在需要預測一張圖片是不是數據7,那么可以用這部分標注數據來訓練一個編碼器,讓編碼器來發現數字7的內在規律,預測時通過編碼器進行計算,比較輸入層與輸出層的相似度,如果相似度較高就可以認為是數字7,編碼和解碼后的圖片示例如下:

實現代碼如下: 

  1 import tensorflow as tf
  2 import numpy as np
  3 import matplotlib.pyplot as plt
  4 
  5 # Import MNIST data
  6 from tensorflow.examples.tutorials.mnist import input_data
  7 
  8 # Parameters
  9 learning_rate = 0.008
 10 training_epochs = 130
 11 batch_size = 2560
 12 
 13 # Building the encoder
 14 def encoder(x,weights,biases):
 15     # Encoder Hidden layer with sigmoid activation #1
 16     layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']),
 17                                    biases['encoder_b1']))
 18     # Decoder Hidden layer with sigmoid activation #2
 19     layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']),
 20                                    biases['encoder_b2']))
 21     return layer_2
 22 
 23 
 24 # Building the decoder
 25 def decoder(x,weights,biases):
 26     # Encoder Hidden layer with sigmoid activation #1
 27     layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']),
 28                                    biases['decoder_b1']))
 29     # Decoder Hidden layer with sigmoid activation #2
 30     layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']),
 31                                    biases['decoder_b2']))
 32     return layer_2
 33     
 34 def one_class_learning(dataset,testset,n_input,one_class_label,filename):
 35     # Network Parameters
 36     n_hidden_1 = int(n_input/2)
 37     n_hidden_2 = int(n_input/4)
 38     # tf Graph input (only pictures)
 39     X = tf.placeholder("float", [None, n_input])
 40 
 41     weights = {
 42         'encoder_h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
 43         'encoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
 44         'decoder_h1': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_1])),
 45         'decoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
 46     }
 47     biases = {
 48         'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
 49         'encoder_b2': tf.Variable(tf.random_normal([n_hidden_2])),
 50         'decoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
 51         'decoder_b2': tf.Variable(tf.random_normal([n_input])),
 52     }
 53     # Construct model
 54     encoder_op = encoder(X,weights,biases)
 55     decoder_op = decoder(encoder_op,weights,biases)
 56     # Prediction
 57     y_pred = decoder_op
 58     # Targets (Labels) are the input data.
 59     y_true = X
 60     # Define loss and optimizer, minimize the squared error
 61     cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2))
 62     optimizer = tf.train.RMSPropOptimizer(learning_rate).minimize(cost)
 63 
 64     # Initializing the variables
 65     init = tf.global_variables_initializer()
 66 
 67     # Launch the graph
 68     with tf.Session() as sess:
 69         sess.run(init)
 70         total_batch = int(len(dataset['data'])/batch_size)
 71         # Training cycle
 72         for epoch in range(training_epochs):
 73             # Loop over all batches
 74             for i in range(total_batch):
 75                 batch_xs = dataset['data'][i*batch_size:(i+1)*batch_size]
 76                 batch_ys = dataset['label'][i*batch_size:(i+1)*batch_size]
 77                 batch_xs = [batch_xs[j] for j in range(len(batch_xs)) if batch_ys[j] == one_class_label]
 78                 
 79                 # Run optimization op (backprop) and cost op (to get loss value)
 80                 _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs})
 81             # Display logs per epoch step
 82             print("Epoch:", '%04d' % (epoch+1),"cost=", "{:.9f}".format(c))
 83 
 84         encode_decode = sess.run(y_pred, feed_dict={X: testset['data']})
 85 
 86         #examples_to_show = 14
 87         #f, a = plt.subplots(2, examples_to_show, figsize=(examples_to_show, 2))
 88         #for i in range(examples_to_show):
 89         #    print(testset['label'][i],sess.run(tf.reduce_mean(tf.pow(testset['data'][i] - encode_decode[i], 2))))
 90         #    a[0][i].imshow(np.reshape(testset['data'][i], (28, 28)))
 91         #    a[1][i].imshow(np.reshape(encode_decode[i], (28, 28)))
 92         #f.show()
 93         #plt.draw()
 94         #plt.waitforbuttonpress()
 95         wf = open(filename,'a+')
 96         for i in range(len(encode_decode)):
 97             wf.write(str(one_class_label)+','+str(testset['label'][i])+','+str(sess.run(tf.reduce_mean(tf.pow(testset['data'][i] - encode_decode[i], 2))))+'\n')
 98             if i % 500 == 0:
 99                 print(i)
100         wf.close()
101         
102         
103         
104 def decode_one_hot(label):
105     return max([i for i in range(len(label)) if label[i] == 1])
106 
107 def mnist_test():
108     mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
109     trainset = {'data':mnist.train.images,'label':[decode_one_hot(label) for label in mnist.train.labels]}
110     testset  = {'data':mnist.test.images,'label':[decode_one_hot(label) for label in mnist.test.labels]}
111     one_class_learning(trainset,testset,784,7,'label_7.csv')
112 
113 mnist_test()

  根據相似度進行排序,還可以計算准確率、召回率、ROC等,這里統計了一下准確率和召回率。

 

四、參考文獻

[1].Manevitz L M, Yousef M. One-class svms for document classification[J]. Journal of Machine Learning Research, 2002, 2(1):139-154.

[2]: http://www.louisdorard.com/blog/when-machine-learning-fails

[3].Manevitz L, Yousef M. One-class document classification via Neural Networks[M]. Elsevier Science Publishers B. V. 2007.

[4].https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/3_NeuralNetworks/autoencoder.py

 

全文完,轉載請注明出處:http://www.cnblogs.com/fengfenggirl/p/One-Class-Learning.html


免責聲明!

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



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