吳裕雄 python 機器學習——人工神經網絡與原始感知機模型
阿新 • • 發佈:2019-05-01
res true 組成 param 個數 its import sample gen
import numpy as np from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D from sklearn.neural_network import MLPClassifier def creat_data(n): ‘‘‘ 創建線性可分數據集 :param n: 正例樣本的個數(同時也是負例樣本的個數) :return: 返回一個線性可分數據集,數據集大小為 2*n ‘‘‘ np.random.seed(1) x_11=np.random.randint(0,100,(n,1)) # 第一組:第一維坐標值 x_12=np.random.randint(0,100,(n,1,))# 第一組:第二維坐標值 x_13=20+np.random.randint(0,10,(n,1,))#第一組: 第三維坐標值 x_21=np.random.randint(0,100,(n,1)) # 第二組:第一維坐標值 x_22=np.random.randint(0,100,(n,1)) # 第二組:第二維坐標值 x_23=10-np.random.randint(0,10,(n,1,)) #第二組:第三維坐標值 new_x_12=x_12*np.sqrt(2)/2-x_13*np.sqrt(2)/2## 沿第一維軸旋轉45度 new_x_13=x_12*np.sqrt(2)/2+x_13*np.sqrt(2)/2## 沿第一維軸旋轉45度 new_x_22=x_22*np.sqrt(2)/2-x_23*np.sqrt(2)/2## 沿第一維軸旋轉45度 new_x_23=x_22*np.sqrt(2)/2+x_23*np.sqrt(2)/2## 沿第一維軸旋轉45度 plus_samples=np.hstack([x_11,new_x_12,new_x_13,np.ones((n,1))]) #拼接成正例數據集 minus_samples=np.hstack([x_21,new_x_22,new_x_23,-np.ones((n,1))]) # 拼接成負例數據集 samples=np.vstack([plus_samples,minus_samples]) # 拼接成完整數據集 np.random.shuffle(samples) # 混洗數據 return samples def creat_data_no_linear(n): ‘‘‘ 創建線性不可分數據集 :param n: 正例樣本的個數(同時也是負例樣本的個數) :return: 返回一個線性不可分數據集,數據集大小為 2*n ‘‘‘ np.random.seed(1) x_11=np.random.randint(0,100,(n,1))# 第一組:第一維坐標值 x_12=np.random.randint(0,100,(n,1,))# 第一組:第二維坐標值 x_13=10+np.random.randint(0,10,(n,1,))#第一組: 第三維坐標值 x_21=np.random.randint(0,100,(n,1))# 第二組:第一維坐標值 x_22=np.random.randint(0,100,(n,1))# 第二組:第二維坐標值 x_23=20-np.random.randint(0,10,(n,1,)) # 第二組:第三維坐標值 new_x_12=x_12*np.sqrt(2)/2-x_13*np.sqrt(2)/2## 沿第一維軸旋轉45度 new_x_13=x_12*np.sqrt(2)/2+x_13*np.sqrt(2)/2## 沿第一維軸旋轉45度 new_x_22=x_22*np.sqrt(2)/2-x_23*np.sqrt(2)/2## 沿第一維軸旋轉45度 new_x_23=x_22*np.sqrt(2)/2+x_23*np.sqrt(2)/2## 沿第一維軸旋轉45度 plus_samples=np.hstack([x_11,new_x_12,new_x_13,np.ones((n,1))])# 拼接成正例數據集 minus_samples=np.hstack([x_21,new_x_22,new_x_23,-np.ones((n,1))])# 拼接成負例數據集 samples=np.vstack([plus_samples,minus_samples])# 拼接成完整數據集 np.random.shuffle(samples) # 混洗數據 return samples def plot_samples(ax,samples): ‘‘‘ 繪制樣本點 :param ax: 繪制圖形所在的 Axes :param samples: 樣本數據集 :return: None ‘‘‘ Y=samples[:,-1] # 標記信息 position_p=Y==1 ## 正類位置 position_m=Y==-1 ## 負類位置 # 繪制正類樣本點 ax.scatter(samples[position_p,0],samples[position_p,1],samples[position_p,2],marker=‘+‘,label=‘+‘,color=‘b‘) # 繪制負類樣本點 ax.scatter(samples[position_m,0],samples[position_m,1],samples[position_m,2],marker=‘^‘,label=‘-‘,color=‘y‘)
def run_plot_samples(): ‘‘‘ 繪制線性可分數據集 :return: None ‘‘‘ fig=plt.figure() ax=Axes3D(fig) data=creat_data(100) # 產生線性可分數據集 plot_samples(ax,data) ax.legend(loc=‘best‘) plt.show() run_plot_samples()
def run_plot_samples_no_linear(): ‘‘‘ 繪制線性不可分數據集 :return: None ‘‘‘ data=creat_data_no_linear(100)# 產生線性不可分數據集 fig=plt.figure() ax=Axes3D(fig) plot_samples(ax,data) ax.legend(loc=‘best‘) plt.show() run_plot_samples_no_linear()
def perceptron(train_data,eta,w_0,b_0): ‘‘‘ 感知機的原始算法 :param train_data: 訓練數據集 :param eta: 學習率 :param w_0: 初始權重向量 :param b_0: 初始的 b :return: 一個元組,依次為:最終的權重向量,最終的 b 值,叠代次數 ‘‘‘ x=train_data[:,:-1] # x 數據 y=train_data[:,-1] # 對應的標記 length= train_data.shape[0] #樣本集大小 w=w_0 b=b_0 step_num=0 while True: i=0 while(i< length): ## 遍歷一輪樣本集中的所有的樣本點 step_num+=1 ‘‘‘ 當應用於線性不可分數據集時,用下面4行代替上面的 step_num+=1 這一行。如果不這麽做,那麽當用於線性 不可分數據集時,叠代永遠不會停止。 step_num+=1 if step_num>=10000000: print("failed!,step_num =%d"%step_num) return ‘‘‘ x_i=x[i].reshape((x.shape[1],1)) # 變成列向量,因為需要執行 np.dot 函數 y_i=y[i] if y_i*(np.dot(np.transpose(w),x_i)+b) <=0: # 該點是誤分類點 w=w+eta*y_i*x_i # 梯度下降 b=b+eta*y_i # 梯度下降 break # 執行下一輪篩選 else:#該點不是誤分類點,選取下一個樣本點 i=i+1 if(i== length): #沒有誤分類點,結束循環 break return (w,b,step_num) def creat_hyperplane(x,y,w,b): ‘‘‘ 創建分離超平面 :param x: 分離超平面上的點的x坐標組成的數組 :param y: 分離超平面上的點的y坐標組成的數組 :param w: 超平面的法向量,它是一個列向量 :param b: 超平面的截距 :return: 分離超平面上的點的z坐標組成的數組 ‘‘‘ return (-w[0][0]*x-w[1][0]*y-b)/w[2][0] # w0*x+w1*y+w2*z+b=0
def run_perceptron(): ‘‘‘ 對線性可分數據集執行感知機的原始算法並繪制分離超平面 ‘‘‘ data=creat_data(100) #產生線性可分數據集 eta,w_0,b_0=0.1,np.ones((3,1),dtype=float),1 # 初始化 學習率、權重、 b w,b,num=perceptron(data,eta,w_0,b_0) # 執行感知機的原始形式 ### 繪圖 fig=plt.figure() plt.suptitle("perceptron") ax=Axes3D(fig) ### 繪制樣本點 plot_samples(ax,data) ## 繪制分離超平面 x=np.linspace(-30,100,100) # 分離超平面的 x坐標數組 y=np.linspace(-30,100,100) # 分離超平面的 y坐標數組 x,y=np.meshgrid(x,y) # 劃分網格 z=creat_hyperplane(x,y,w,b) # 分離超平面的 z坐標數組 ax.plot_surface(x, y, z, rstride=1, cstride=1,color=‘g‘,alpha=0.2) ax.legend(loc="best") plt.show() run_perceptron()
def perceptron_nolinear(train_data,eta,w_0,b_0): ‘‘‘ 感知機的原始算法 :param train_data: 訓練數據集 :param eta: 學習率 :param w_0: 初始權重向量 :param b_0: 初始的 b :return: 一個元組,依次為:最終的權重向量,最終的 b 值,叠代次數 ‘‘‘ x=train_data[:,:-1] # x 數據 y=train_data[:,-1] # 對應的標記 length= train_data.shape[0] #樣本集大小 w=w_0 b=b_0 step_num=0 while True: i=0 while(i< length): ## 遍歷一輪樣本集中的所有的樣本點 step_num+=1 if step_num>=10000000: print("failed!,step_num =%d"%step_num) return x_i=x[i].reshape((x.shape[1],1)) # 變成列向量,因為需要執行 np.dot 函數 y_i=y[i] if y_i*(np.dot(np.transpose(w),x_i)+b) <=0: # 該點是誤分類點 w=w+eta*y_i*x_i # 梯度下降 b=b+eta*y_i # 梯度下降 break # 執行下一輪篩選 else:#該點不是誤分類點,選取下一個樣本點 i=i+1 if(i== length): #沒有誤分類點,結束循環 break return (w,b,step_num) def creat_hyperplane(x,y,w,b): ‘‘‘ 創建分離超平面 :param x: 分離超平面上的點的x坐標組成的數組 :param y: 分離超平面上的點的y坐標組成的數組 :param w: 超平面的法向量,它是一個列向量 :param b: 超平面的截距 :return: 分離超平面上的點的z坐標組成的數組 ‘‘‘ return (-w[0][0]*x-w[1][0]*y-b)/w[2][0] # w0*x+w1*y+w2*z+b=0
def run_perceptron_no_linear(): ‘‘‘ 對線性不可分數據集執行感知機的元素算法 ‘‘‘ data=creat_data_no_linear(100)#產生線性不可分數據集 perceptron_nolinear(data,eta=0.1,w_0=np.zeros((3,1)),b_0=0) run_perceptron_no_linear()
def creat_w(train_data,alpha): ‘‘‘ 根據訓練數據集和 alpha向量 創建 權重向量 :param train_data: 訓練數據集 :param alpha: alpha 向量 :return: 權重向量 ‘‘‘ x=train_data[:,:-1] # x 數據 y=train_data[:,-1] # 對應的分類 N= train_data.shape[0] #樣本集大小 w=np.zeros((x.shape[1],1)) for i in range(0,N): w=w+alpha[i][0]*y[i]*(x[i].reshape(x[i].size,1)) return w
def perceptron_dual(train_data,eta,alpha_0,b_0): ‘‘‘ 感知機的對偶形式算法 :param train_data: 訓練數據集 :param eta: 學習率 :param alpha_0: 初始的 alpha 向量 :param b_0: 初始的 b 值 :return: 一個元組,依次為:最終的alpha 向量、最終的 b 值、叠代次數 ‘‘‘ x=train_data[:,:-1] # x 數據 y=train_data[:,-1] # 對應的分類 length= train_data.shape[0] #樣本集大小 alpha=alpha_0 b=b_0 step_num=0 while True: i=0 while(i< length): step_num+=1 x_i=x[i].reshape((x.shape[1],1)) # 變形為列向量,因為需要調用 np.dot y_i=y[i] w=creat_w(train_data,alpha) z=y_i*(np.dot(np.transpose(w),x_i)+b) if z <=0: # 該點是誤分類點 alpha[i][0]+=eta # 梯度下降 b+=eta*y_i # 梯度下降 break # 梯度下降了,從頭開始,執行下一輪篩選 else: i=i+1 #該點不是誤分類點,選取下一個樣本點 if(i== length ): #沒有誤分類點,結束循環 break return (alpha,b,step_num) def run_perceptron_dual(): ‘‘‘ 對線性可分數據集執行感知機的原始算法和對偶形式算法,並繪制分離超平面 ‘‘‘ data=creat_data(100) eta,w_0,b_0=0.1,np.ones((3,1),dtype=float),1 w_1,b_1,num_1=perceptron(data,eta,w_0,b_0) ##執行原始形式的算法 alpha,b_2,num_2=perceptron_dual(data,eta=0.1,alpha_0=np.zeros((data.shape[0]*2,1)), b_0=0) # 執行對偶形式的算法 w_2=creat_w(data,alpha) print("w_1,b_1",w_1,b_1) print("w_2,b_2",w_2,b_2) ## 繪圖 fig=plt.figure() plt.suptitle("perceptron") ax=Axes3D(fig) ### 繪制樣本點 plot_samples(ax,data) ## 繪制分離超平面 x=np.linspace(-30,100,100) # 分離超平面的 x坐標數組 y=np.linspace(-30,100,100) # 分離超平面的 y坐標數組 x,y=np.meshgrid(x,y) # 劃分網格 z=creat_hyperplane(x,y,w_1,b_1) # 原始形式算法的分離超平面的 z坐標數組 z_2=creat_hyperplane(x,y,w_2,b_2) # 對偶形式算法的分離超平面的 z坐標數組 ax.plot_surface(x, y, z, rstride=1, cstride=1,color=‘g‘,alpha=0.2) ax.plot_surface(x, y, z_2, rstride=1, cstride=1,color=‘c‘,alpha=0.2) ax.legend(loc="best") plt.show() run_perceptron_dual()
def test_eta(data,ax,etas,w_0,alpha_0,b_0): ‘‘‘ 測試學習率對於感知機兩種形式算法的收斂速度的影響 :param data: 訓練數據集 :param ax: Axes實例,負責繪制圖形 :param etas: 候選的學習率的值組成的列表 :param w_0: 原始算法用到的初始權重向量 :param alpha_0: 對偶形式用到的初始 alpha 向量 :param b_0: 初始 b 值 :return: None ‘‘‘ nums1=[] nums2=[] for eta in etas: _,_,num_1=perceptron(data,eta,w_0=w_0,b_0=b_0) # 獲取原始形式算法的叠代次數 _,_,num_2=perceptron_dual(data,eta=0.1,alpha_0=alpha_0,b_0=b_0) # 獲取對偶形式算法的叠代次數 nums1.append(num_1) nums2.append(num_2) ax.plot(etas,np.array(nums1),label=‘orignal iteraton times‘) ax.plot(etas,np.array(nums2),label=‘dual iteraton times‘) def run_test_eta(): fig=plt.figure() fig.suptitle("perceptron") ax=fig.add_subplot(1,1,1) ax.set_xlabel(r‘$\eta$‘) data=creat_data(20) # 創建線性可分數據集 etas=np.linspace(0.01,1,num=25,endpoint=False) w_0,b_0,alpha_0=np.ones((3,1)),0,np.zeros((data.shape[0],1)) test_eta(data,ax,etas,w_0,alpha_0,b_0) ax.legend(loc="best",framealpha=0.5) plt.show() run_test_eta()
吳裕雄 python 機器學習——人工神經網絡與原始感知機模型