程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

鸢尾花完整的python代碼(鸢尾花分類)

編輯:Python

大家好,又見面了,我是你們的朋友全棧君。

. 邏輯回歸

邏輯回歸(Logistic Regression)是用於處理因變量為分類變量的回歸問題,常見的是二分類或二項分布問題,也可以處理多分類問題,它實際上是屬於一種分類方法。

概率p與因變量往往是非線性的,為了解決該類問題,我們引入了logit變換,使得logit(p)與自變量之 間存在線性相關的關系,邏輯回歸模型定義如下:

1 #Sigmoid曲線:

2 importmatplotlib.pyplot as plt3 importnumpy as np4

5 defSigmoid(x):6 return 1.0 / (1.0 + np.exp(-x))7

8 x= np.arange(-10, 10, 0.1)9 h = Sigmoid(x) #Sigmoid函數

10 plt.plot(x, h)11 plt.axvline(0.0, color=’k’) #坐標軸上加一條豎直的線(0位置)

12 plt.axhspan(0.0, 1.0, facecolor=’1.0′, alpha=1.0, ls=’dotted’)13 plt.axhline(y=0.5, ls=’dotted’, color=’k’) #在y=0.5的地方加上黑色虛線

14 plt.yticks([0.0, 0.5, 1.0]) #y軸標度

15 plt.ylim(-0.1, 1.1) #y軸范圍

16 plt.show()

二、鸢尾花分類問題的思路分析

(1)選擇使用LogisticRegression分類器,由於Iris數據集涉及到3個目標分類問題,而邏輯回歸模型是二分類模型,用於二分類問題。因此,可以將其推廣為多項邏輯回歸模型(multi-nominal logistic regression model),用於多分類。

(2)根據多項邏輯回歸模型,編寫代碼,輸入數據集,訓練得到相應參數並作出預測。

(3)對預測出的數據的分類結果和原始數據進行可視化展示。

三、多項邏輯回歸模型的原理及推導過程

假設類別Y 的取值集合為 {1,2,…,K},那麼多項邏輯回歸模型是:

其似然函數為:

其中,

為模型在輸入樣本

時,將其判為類別k 的概率;

起到指示函數的作用,當K 等於樣本

的標簽類別時為1,其余均為0。

對似然函數取對數,然後取負,得到

(簡記為:

),最終要訓練出的模型參數要使得

的值取得最小。

的推導過程如下:

考慮到過擬合的發生,對

加上一個正則項:

可以寫成:

關於

求梯度,得到:

在上式中,第一項

可以看成是類別k的後驗期望值,第二項

視為類別k 的先驗期望值,第三項是正則化項,用於緩解過擬合。

接下來使用梯度下降法對參數

進行修正更新即可:

四、實現步驟

4.1 讀入數據文件

這裡需要注意的是,在datas中取前兩列作為特征(為了後期的可視化畫圖更加直觀,故只取前兩列特征值向量進行訓練)

1 attributes=[‘SepalLength’,’SepalWidth’,’PetalLength’,’PetalWidth’] #鸢尾花的四個屬性名

2

3 datas=[]4 labels=[]5

6 #with open(‘IRIS_dataset.txt’,’r’) as f:

7 #for line in f:

8 #linedata=line.split(‘,’)

9 #datas.append(linedata[:-1]) #前4列是4個屬性的值

10 #labels.append(linedata[-1].replace(‘\n’,”)) #最後一列是類別

11

12 #讀入數據集的數據:

13 data_file=open(‘IRIS_dataset.txt’,’r’)14 for line indata_file.readlines():15 #print(line)

16 linedata = line.split(‘,’)17 #datas.append(linedata[:-1]) # 前4列是4個屬性的值(誤判的樣本的個數為:7

18 datas.append(linedata[:-3]) #前2列是2個屬性的值(誤判的樣本的個數為:30

19 labels.append(linedata[-1].replace(‘\n’, ”)) #最後一列是類別

20

21 datas=np.array(datas)22 datas=datas.astype(float) #將二維的字符串數組轉換成浮點數數組

23 labels=np.array(labels)24 kinds=list(set(labels)) #3個類別的名字列表

4.2編寫代碼實現LogisticRegression算法

1 #LogisticRegression算法,訓練數據,傳入參數為數據集(包括特征數據及標簽數據),結果返回訓練得到的參數 W

2 defLogRegressionAlgorithm(datas,labels):3 kinds = list(set(labels)) #3個類別的名字列表

4 means=datas.mean(axis=0) #各個屬性的均值

5 stds=datas.std(axis=0) #各個屬性的標准差

6 N,M= datas.shape[0],datas.shape[1]+1 #N是樣本數,M是參數向量的維

7 K=3 #k=3是類別數

8

9 data=np.ones((N,M))10 data[:,1:]=(datas-means)/stds #對原始數據進行標准差歸一化

11

12 W=np.zeros((K-1,M)) #存儲參數矩陣

13 priorEs=np.array([1.0/N*np.sum(data[labels==kinds[i]],axis=0) for i in range(K-1)]) #各個屬性的先驗期望值

14

15 liklist=[]16 for it in range(1000):17 lik=0 #當前的對數似然函數值

18 for k in range(K-1): #似然函數值的第一部分

19 lik -= np.sum(np.dot(W[k],data[labels==kinds[k]].transpose()))20 lik +=1.0/N *np.sum(np.log(np.sum(np.exp(np.dot(W,data.transpose())),axis=0)+1)) #似然函數的第二部分

21 liklist.append(lik)22

23 wx=np.exp(np.dot(W,data.transpose()))24 probs=np.divide(wx,1+np.sum(wx,axis=0).transpose()) #K-1 *N的矩陣

25 posteriorEs=1.0/N*np.dot(probs,data) #各個屬性的後驗期望值

26 gradients=posteriorEs – priorEs +1.0/100 *W #梯度,最後一項是高斯項,防止過擬合

27 W -= gradients #對參數進行修正

28 print(“輸出W為:”,W)29 return W

4.3 編寫predict_fun()預測函數

根據訓練得到的參數W和數據集,進行預測。輸入參數為數據集和由LogisticRegression算法得到的參數W,返回值為預測的值。

1 #根據訓練得到的參數W和數據集,進行預測。輸入參數為數據集和由LogisticRegression算法得到的參數W,返回值為預測的值

2 defpredict_fun(datas,W):3 N, M = datas.shape[0], datas.shape[1] + 1 #N是樣本數,M是參數向量的維

4 K = 3 #k=3是類別數

5 data =np.ones((N, M))6 means = datas.mean(axis=0) #各個屬性的均值

7 stds = datas.std(axis=0) #各個屬性的標准差

8 data[:, 1:] = (datas – means) / stds #對原始數據進行標准差歸一化

9

10 #probM每行三個元素,分別表示data中對應樣本被判給三個類別的概率

11 probM =np.ones((N, K))12 print(“data.shape:”, data.shape)13 print(“datas.shape:”, datas.shape)14 print(“W.shape:”, W.shape)15 print(“probM.shape:”, probM.shape)16 probM[:, :-1] =np.exp(np.dot(data, W.transpose()))17 probM /= np.array([np.sum(probM, axis=1)]).transpose() #得到概率

18

19 predict = np.argmax(probM, axis=1).astype(int) #取最大概率對應的類別

20 print(“輸出predict為:”, predict)21 return predict

4.4繪制圖像

(1)確定坐標軸范圍,x,y軸分別表示兩個特征

1 #1.確定坐標軸范圍,x,y軸分別表示兩個特征

2 x1_min, x1_max = datas[:, 0].min(), datas[:, 0].max() #第0列的范圍

3 x2_min, x2_max = datas[:, 1].min(), datas[:, 1].max() #第1列的范圍

4 x1, x2 = np.mgrid[x1_min:x1_max:150j, x2_min:x2_max:150j] #生成網格采樣點,橫軸為屬性x1,縱軸為屬性x2

5 grid_test = np.stack((x1.flat, x2.flat), axis=1) #測試點

6 #.flat 函數將兩個矩陣都變成兩個一維數組,調用stack函數組合成一個二維數組

7 print(“grid_test = \n”, grid_test)8

9 grid_hat = predict_fun(grid_test,W) #預測分類值

10 grid_hat = grid_hat.reshape(x1.shape) #使之與輸入的形狀相同

11 #grid_hat本來是一唯的,調用reshape()函數修改形狀,將其grid_hat轉換為兩個特征(長度和寬度)

12 print(“grid_hat = \n”, grid_hat)13 print(“grid_hat.shape: = \n”, grid_hat.shape) #(150, 150)

(2)指定默認字體

1 #2.指定默認字體

2 mpl.rcParams[‘font.sans-serif’] = [u’SimHei’]3 mpl.rcParams[‘axes.unicode_minus’] = False

(3)繪制圖像

1 #3.繪制圖像

2 cm_light = mpl.colors.ListedColormap([‘#A0FFA0’, ‘#FFA0A0’, ‘#A0A0FF’])3 cm_dark = mpl.colors.ListedColormap([‘g’, ‘r’, ‘b’])4

5 alpha = 0.5

6

7 plt.pcolormesh(x1, x2, grid_hat, cmap=plt.cm.Paired) #預測值的顯示

8 #調用pcolormesh()函數將x1、x2兩個網格矩陣和對應的預測結果grid_hat繪制在圖片上

9 #可以發現輸出為三個顏色區塊,分布表示分類的三類區域。cmap=plt.cm.Paired/cmap=cm_light表示繪圖樣式選擇Paired主題

10 #plt.scatter(datas[:, 0], datas[:, 1], c=labels, edgecolors=’k’, s=50, cmap=cm_dark) # 樣本

11 plt.plot(datas[:, 0], datas[:, 1], ‘o’, alpha=alpha, color=’blue’, markeredgecolor=’k’)12 ##繪制散點圖

13 plt.scatter(datas[:, 0], datas[:, 1], s=120, facecolors=’none’, zorder=10) #圈中測試集樣本

14 plt.xlabel(u’花萼長度’, fontsize=13) #X軸標簽

15 plt.ylabel(u’花萼寬度’, fontsize=13) #Y軸標簽

16 plt.xlim(x1_min, x1_max) #x 軸范圍

17 plt.ylim(x2_min, x2_max) #y 軸范圍

18 plt.title(u’鸢尾花LogisticRegression二特征分類’, fontsize=15)19 #plt.legend(loc=2) # 左上角繪制圖標

20 #plt.grid()

21 plt.show()

五、實驗結果

(1)運行程序輸出的參數:

使用二個特征:

輸出W為: [[-0.41462351 1.26263398 0.26536423]

[-1.07260354 -2.44478672 1.96448439]]

輸出predict為: [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 0 0 0 2 0 2 0 2 0 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 2 2 0 2 2 0 2 0 0 0 0 2 0 0 0 0 0 0 2 2 0 0 0 0 2 0 2 0 0 0 0 2 2 0 0 0 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 2]

誤判的樣本的個數為:28

使用四個特征:

輸出W為:

[[-0.09363942 -1.41359443 1.17376524 -2.3116611 -2.20018596]

[ 1.44071982 -0.05960463 -0.31391519 -0.87589944 -1.83255315]]

輸出predict為: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]

誤判的樣本的個數為:8

(2)數據可視化結果如下:

六、結果分析與比較

由以上實驗結果可以看出,使用了二特征的誤判的樣本個數為28(樣本總數為150),而使用了四個特征的訓練結果,誤判的樣本個數為8,在一定程度上可以解釋使用的特征數過少的話,會導致欠擬合的情況發生。

為了後期的可視化畫圖更加直觀,故只取前兩列特征值向量進行訓練。結果展示如上圖所示。

完整實現代碼詳見:【GitHub 】

【Reference】

發布者:全棧程序員棧長,轉載請注明出處:https://javaforall.cn/128853.html原文鏈接:https://javaforall.cn


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved