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,損失函數定義為 1/n ∑max(0,1-y_i (ωx_i+b)) +α∥ω∥^2 ,其中, α 為軟正則化係數,在這裡,我們設置為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 |