1. 程式人生 > >TensorFlow深度學習框架學習(二):TensorFlow實現線性支援向量機(SVM)

TensorFlow深度學習框架學習(二):TensorFlow實現線性支援向量機(SVM)

SVM的原理可以參考李航的《統計學習方法》
具體程式碼如下,程式碼都有註釋的

#1、匯入必要的庫
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from sklearn import datasets

#2、建立一個計算圖會話,載入需要的資料集。
sess = tf.Session()
iris = datasets.load_iris()
#在iris中的data這個欄位裡面,取第一列(其為花萼長度)和第四列(為花萼寬度)的特徵變數
x_vals = np.array([[x[0], x[3
]] for x in iris.data]) #iris中的target欄位裡面有3個數值:0,1,2;其中將0(山鳶尾花)都設定為1,其他都設定為-1 y_vals = np.array([1 if y==0 else -1 for y in iris.target]) #3、將資料集分割為:訓練集和測試集; #訓練集的x和y分別為x_vals_train 和 y_vals_train #測試集的x和y分別為x_vals_test 和 y_vals_test 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] #4、設定批量大小,佔位符,模型變數 batch_size = 100 x_data = tf.placeholder(shape=[None, 2], dtype=tf.float32) y_target = tf.placeholder(shape=[None
, 1], dtype=tf.float32) #這裡的A,其實就是ω A = tf.Variable(tf.random_normal(shape=[2,1])) b = tf.Variable(tf.random_normal(shape=[1,1])) #5、宣告模型輸出 model_output = tf.subtract(tf.matmul(x_data, A), b) #6、宣告最大間隔損失函式,這裡的損失函式是特定的一個損失函式,詳見《TensorFlow機器學習指南》68頁 #定義一個函式來計算向量的L2範數。 l2_norm = tf.reduce_sum(tf.square(A)) #增加間隔引數α= 0.1 alpha = tf.constant([0.01]) classification_term = tf.reduce_mean(tf.maximum(0., tf.subtract(1., tf.multiply(model_output, y_target)))) loss = tf.add(classification_term, tf.multiply(alpha, l2_norm)) #7、宣告預測函式和準確度函式,用來評估訓練集和測試集訓練的準確度: prediction = tf.sign(model_output) accuracy = tf.reduce_mean(tf.cast(tf.equal(prediction, y_target), tf.float32)) #8、宣告優化器函式 my_opt = tf.train.GradientDescentOptimizer(0.01) train_step = my_opt.minimize(loss) #初始化模型程式碼 init = tf.global_variables_initializer() sess.run(init) #9、遍歷迭代訓練模型,記錄訓練集和測試集訓練的損失和準確度 loss_vec = [] train_accuracy = [] test_accuracy = [] for i in range(1000): 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) + ' A = ' + str(sess.run(A)) + ' b = ' + str(sess.run(b))) print('Loss = ' + str(temp_loss)) ''' #10、抽取資料 [[a1], [a2]] = sess.run(A) [ [b] ] = sess.run(b) #slope是斜率的意思,intercept是截距的意思 slope = -a2/a1 y_intercept = b/a1 #下面這句話的意思是將x_vals中的第二列單獨取出賦值給x1_vals x1_vals = [d[1] for d in x_vals] #best_fit這個best_fit是根據x1_vals計算出超平面上的x0_vals值 #超平面是a1 * x0_vals + a2 * x1_vals - b = 0 所以 x0_vals = -a2/a1 * x1_vals + b/a1 ; best_fit = [] for i in x1_vals: best_fit.append(slope*i+y_intercept) #setosa表示山鳶尾花,enumerate表示列舉 #為什麼底下用enumerate?因為i表示的是x_vals的索引值,而使用enumerate可以直接獲得x_vals的索引值 setosa_x = [d[1] for i,d in enumerate(x_vals) if y_vals[i]==1] setosa_y = [d[0] for i,d in enumerate(x_vals) if y_vals[i]==1] #not_setosa表示不是山鳶尾花 not_setosa_x = [d[1] for i,d in enumerate(x_vals) if y_vals[i]==-1] not_setosa_y = [d[0] for i,d in enumerate(x_vals) if y_vals[i]==-1] #12、使用Python程式碼繪製資料的線性分類器、準確度和損失圖 #首先,先畫出將樣本分類的圖 plt.plot(setosa_x, setosa_y, 'o', label='setosa') plt.plot(not_setosa_x, not_setosa_y, 'x', label='not-setosa') plt.plot(x1_vals, best_fit, 'r-', label='Linear Separator', linewidth=3) plt.ylim([0, 10]) plt.legend(loc='lower right') plt.title('Sepal Length vs Pedal Width') plt.xlabel('Pedal Width') plt.ylabel('Sepal Length') plt.show() #訓練集和測試集迭代的準確度 plt.plot(train_accuracy, 'k-', label='Training Accuracy') plt.plot(test_accuracy, 'r--', label='Test Accuracy') plt.title('Train and Test Set Accuracise') plt.xlabel('Generation') plt.ylabel('Accuracy') plt.legend(loc='lower right') plt.show() #最大間隔圖 plt.plot(loss_vec, 'k-') plt.title('Loss per Generation') plt.xlabel('Generation') plt.ylabel('Loss') plt.show()

最後得到的結果如下:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述