Tensorflow實現二分類線性SVM
- 首先進行包的導入:
import matplotlib.pyplot as pltimport numpy as npimport tensorflow as tffrom sklearn import datasets
- 為了使畫出的圖可以出現中文,添加如下語句:
from pylab import mpl mpl.rcParams[font.sans-serif] =[SimHei]
- 為了使實驗可以重複進行,添加如下語句(當然如果僅僅為了測試,也可以不用添加):
np.random.seed(1)tf.set_random_seed(1)
- 創建Tensorflow會話:
sess=tf.Session()
- 產生數據源,在這裡我們使用sklearn自帶的iris數據集。該數據集為鳶尾花數據集,一共有150個數據:這些數據分為3類(山鳶尾、雜色鳶尾和維吉尼亞鳶尾),每類50個數據。這些數據主要包括四個屬性:萼片長度、萼片寬度、花瓣長度、花瓣寬度。在這裡我們主要實現二分類,所以將山鳶尾標籤置為1,其他兩種為-1。
iris=datasets.load_iris()x_vals=iris.datay_vals=np.array([1 if y==0 else-1 for y in iris.target])
- 接下來,將數據集劃分為訓練集和測試集,這裡我們使用np.random.choice()方法來隨機劃分。其中,x_vals_train、y_vals_train為訓練集的樣本和標籤,x_vals_test和y_vals_test為測試集的樣本和標籤。測試集和訓練集的比例我們設置為8:2。
train_indices=np.random.choice(len(x_vals),round(len(x_vals)*0.8), replace=False)test_indices=np.array(list(set(range(len(x_vals)))-set(train_indices)))x_vals_train =x_vals[train_indices]x_vals_test =x_vals[test_indices]y_vals_train =y_vals[train_indices]y_vals_test =y_vals[test_indices]
- 我們利用隨機梯度下降法進行訓練。設置每次訓練中選取樣本的容量。
batch_size = 100
- 設定Tensorflow參變數。x_data為輸入,y_target為真實標籤,W和b為超平面的參數。
x_data =tf.placeholder(shape=[None, 4], dtype=tf.float32)y_target =tf.placeholder(shape=[None, 1], dtype=tf.float32)W = tf.Variable(tf.random_normal(shape=[4,1]))b =tf.Variable(tf.random_normal(shape=[1,1]))
- 接下來定義可以優化的損失函數。在SVM中,我們利用Hinge Loss作為損失函數。計算結果為model_output,損失函數定義為 ,其中, 為軟正則化係數,在這裡,我們設置為0.1。
model_output=tf.matmul(x_data,W)+bl2_norm =tf.reduce_sum(tf.square(W))alpha = tf.constant([0.1])classification_term =tf.reduce_mean(tf.maximum(0.,1.-model_output*y_target))loss =classification_term+alpha*l2_norm
- 定義模型輸出。利用符號函數實現,結果大於0時,輸出1,小於0時,輸出-1。
prediction =tf.sign(model_output)
- 定義準確率,利用的是一批樣本的平均準確率。
accuracy =tf.reduce_mean(tf.cast(tf.equal(prediction, y_target),tf.float32))
- 定義訓練步驟。
train_step=tf.train.GradientDescentOptimizer(0.01).minimize(loss)
- 開始訓練,初始化所有變數。
sess.run(tf.global_variables_initializer())
- 為了方便直觀顯示,我們定義三個數組,分別對應訓練誤差、訓練準確率和測試準確率。
loss_vec = []train_accuracy = []test_accuracy = []
- 在每次迭代過程當中,首先隨機選擇訓練的樣本,然後進行訓練。我們設置迭代次數為200次。
for i in range(500): rand_index =np.random.choice(len(x_vals_train), size=batch_size) rand_x = x_vals_train[rand_index] rand_y =np.transpose([y_vals_train[rand_index]]) sess.run(train_step, feed_dict={x_data:rand_x, y_target:rand_y})
- 接下來就是直觀顯示結果的東西了
for i in range(500): ...... temp_loss = sess.run(loss,feed_dict={x_data: rand_x, y_target: rand_y}) loss_vec.append(temp_loss) train_acc_temp=sess.run(accuracy,feed_dict={x_data: x_vals_train,y_target: np.transpose([y_vals_train])}) train_accuracy.append(train_acc_temp) test_acc_temp=sess.run(accuracy,feed_dict={x_data: x_vals_test,y_target: np.transpose([y_vals_test])}) test_accuracy.append(test_acc_temp) if (i+1)%100==0: print(Step # + str(i+1) + W = +str(sess.run(W)) + b = + str(sess.run(b))) print(Loss = + str(loss))plt.plot(loss_vec)plt.plot(train_accuracy)plt.plot(test_accuracy)plt.legend([損失,訓練精確度,測試精確度])plt.ylim(0.,1.)
完整代碼如下:
# -*- coding: utf-8 -*-import matplotlib.pyplot as pltimport numpy as npimport tensorflow as tffrom sklearn import datasetsfrom pylab import mplmpl.rcParams[font.sans-serif] = [SimHei] np.random.seed(1)tf.set_random_seed(1)sess=tf.Session()#產生數據iris=datasets.load_iris()x_vals=iris.datay_vals=np.array([1 if y==0 else -1 for y in iris.target])#劃分數據為訓練集和測試集train_indices = np.random.choice(len(x_vals),round(len(x_vals)*0.8), replace=False)test_indices = np.array(list(set(range(len(x_vals))) - set(train_indices)))x_vals_train = x_vals[train_indices]x_vals_test = x_vals[test_indices]y_vals_train = y_vals[train_indices]y_vals_test = y_vals[test_indices]#批訓練中批的大小batch_size = 100x_data = tf.placeholder(shape=[None, 4], dtype=tf.float32)y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)W = tf.Variable(tf.random_normal(shape=[4,1]))b = tf.Variable(tf.random_normal(shape=[1,1]))#定義損失函數model_output=tf.matmul(x_data,W)+bl2_norm = tf.reduce_sum(tf.square(W))#軟正則化參數alpha = tf.constant([0.1])#定義損失函數classification_term = tf.reduce_mean(tf.maximum(0.,1.-model_output*y_target))loss = classification_term+alpha*l2_norm#輸出prediction = tf.sign(model_output)accuracy = tf.reduce_mean(tf.cast(tf.equal(prediction, y_target),tf.float32))train_step=tf.train.GradientDescentOptimizer(0.01).minimize(loss)#開始訓練sess.run(tf.global_variables_initializer())loss_vec = []train_accuracy = []test_accuracy = []for i in range(200): rand_index = np.random.choice(len(x_vals_train), size=batch_size) rand_x = x_vals_train[rand_index] rand_y = np.transpose([y_vals_train[rand_index]]) sess.run(train_step, feed_dict={x_data: rand_x, y_target:rand_y}) temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y}) loss_vec.append(temp_loss) train_acc_temp = sess.run(accuracy, feed_dict={x_data: x_vals_train, y_target: np.transpose([y_vals_train])}) train_accuracy.append(train_acc_temp) test_acc_temp = sess.run(accuracy, feed_dict={x_data: x_vals_test, y_target: np.transpose([y_vals_test])}) test_accuracy.append(test_acc_temp) if (i+1)%100==0: print(Step # + str(i+1) + W = + str(sess.run(W)) + b = + str(sess.run(b))) print(Loss = + str(test_acc_temp))plt.plot(loss_vec)plt.plot(train_accuracy)plt.plot(test_accuracy)plt.legend([損失,訓練精確度,測試精確度])plt.ylim(0.,1.)
最後的結果:
大約在第90次迭代時能達到100%的預測準確率。
推薦閱讀:
※複習:SVM
※SVM—線性支持向量機—二類分類模型
※機器學習演算法實踐-SVM核函數和軟間隔
※機器學習演算法實踐-Platt SMO和遺傳演算法優化SVM
※BAT機器學習面試1000題系列(241-245)
TAG:SVM | 機器學習 | TensorFlow |