下面分別采用的是k近鄰演算法(KNN)和SVM實作的手寫數字識別,

資料集:
百度網盤提取碼:j13s
CSDN資源
專案訓練目標
- 學會呼叫資料集, 利用Python相關程式從資料集中讀取資料
- 學會根據資料集訓練分類器, 并在Python下實作演算法
- 學會運用已學的知識完成實際資料集的分類程式
- 學會觀察分析演算法里相關引數的意義,作用及其對結果產生的影響
- 學會對不同演算法進行比較并學會分析各個演算法優缺點
進入正文啦,如果是小白,不會安裝模塊的話,可以看看我哦
匯入模塊
- 首先我們要匯入所需要的庫
from sklearn.model_selection import GridSearchCV
from sklearn import svm
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
import operator
import pandas as pd
import numpy as np
import os
import pprint
import matplotlib.pyplot as plt
from matplotlib.pylab import style
- 同時設定下matplotlib繪圖中文顯示亂碼問題
%matplotlib inline
#解決中文顯示問題
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
- 切換到資料的路徑
path = r"C:\Users\Administrator\homework\機器學習\digits"
os.chdir(path)
讀取資料
訓練集
# 獲取資料檔案
fileList = os.listdir(r'trainingDigits')
# 定義資料標簽串列
y_train = []
# 添加資料標簽
for filename in fileList:
y_train.append(int(filename.split('_')[0]))
# 定義矩陣資料格式
x_train = np.zeros((len(y_train),32*32))
# 獲取矩陣資料
index = 0
for filename in fileList:
with open(r'trainingDigits\%s'%filename, 'rb') as f:
# 定義一個空矩陣
vect = np.zeros((1,1024))
# 回圈32行
for i in range(32):
# 讀取每一行資料
line = f.readline()
# 遍歷每行資料索引 line[j] 即為資料
for j in range(32):
vect[0,32*i+j] = int(line[j])
x_train[index,:] = vect
index+=1
觀察資料的結構
x_train.shape
(1934, 1024)
資料分布
df = pd.DataFrame(y_train,columns=["數字"])
a = df["數字"].value_counts().sort_values()
分布情況

測驗集
fileList2 = os.listdir(r'testDigits')
# 定義資料標簽串列
y_test = []# 獲取資料標簽
for filename2 in fileList2:
y_test.append(int(filename2.split('_')[0]))
# 定義矩陣資料格式
x_test = np.zeros((len(y_test),1024))
# 獲取矩陣資料
index = 0
for filename2 in fileList2:
with open(r'testDigits\%s'%filename2, 'rb') as f:
# 定義一個空矩陣
vect = np.zeros((1,1024))
# 回圈32行
for i in range(32):
# 讀取每一行資料
line = f.readline()
# 遍歷每行資料索引 line[j] 即為資料
for j in range(32):
vect[0,32*i+j] = int(line[j])
x_test[index,:] = vect
index+=1
資料分布
df = pd.DataFrame(y_test,columns=["數字"])
c = df["數字"].value_counts().sort_index()

- 通過對資料分布的,可知資料在測驗集和訓練集中分布平穩
模型構造
KNN
error = 0
total = len(y_train)
def KNN(n_neighbors):
knn = KNeighborsClassifier(n_neighbors=n_neighbors)#超引數N
#利用訓練資料擬合模型
knn.fit(x_train,y_train)
# 預測資料
y_predict = knn.predict(x_test)
# print(1 - sum(y_predict ==y_test)/len(y_predict))
print("超引數n="+str(n_neighbors)+"時,模型的錯誤率:"+str(1 - knn.score(x_test,y_test)))
return 1-knn.score(x_test,y_test)
correct=[]
for i in range(1,11):
correct.append(KNN(i))
超引數n=1時,模型的錯誤率:0.01374207188160681
超引數n=2時,模型的錯誤率:0.023255813953488413
超引數n=3時,模型的錯誤率:0.012684989429175508
超引數n=4時,模型的錯誤率:0.016913319238900604
超引數n=5時,模型的錯誤率:0.019027484143763207
超引數n=6時,模型的錯誤率:0.022198731501057112
超引數n=7時,模型的錯誤率:0.023255813953488413
超引數n=8時,模型的錯誤率:0.024312896405919715
超引數n=9時,模型的錯誤率:0.026427061310782207
超引數n=10時,模型的錯誤率:0.024312896405919715
繪制不同k值下錯誤率圖形

使用交叉驗證網格搜索的方式選擇最優模型
estimator = KNeighborsClassifier()
param_dict = {"n_neighbors": [1,2,3,4,5,6,7,8,9,10]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=3)
estimator.fit(x_train,y_train)
y_predict = estimator.predict(x_test)
#print("比對預測結果和真實值:\n", y_predict == y_test)
score = estimator.score(x_test, y_test)
print("直接計算準確率:\n", score)
直接計算準確率:
0.9873150105708245
使用f1-score來對進行模型評估
from sklearn.metrics import classification_report
target_names = [str(i) for i in range(0,10)]
print(classification_report(y_test, y_predict, target_names=target_names))
precision recall f1-score support
0 1.00 1.00 1.00 87
1 0.96 0.99 0.97 97
2 1.00 1.00 1.00 92
3 0.98 0.99 0.98 85
4 1.00 1.00 1.00 114
5 0.99 0.98 0.99 108
6 0.98 1.00 0.99 87
7 0.98 1.00 0.99 96
8 1.00 0.95 0.97 91
9 0.99 0.97 0.98 89
accuracy 0.99 946
macro avg 0.99 0.99 0.99 946
weighted avg 0.99 0.99 0.99 946
模型小結
- 根據 knn 模型錯誤率圖可知,當增大 k 值時,錯誤率會先降低,因為有周圍更多的樣本可以借鑒了,分類效果會變好,但當 K 值更大時,錯誤率會逐漸增高,在本模型中,當 k=3 時模型得錯誤率最低,
SVM
接下來使用支持向量機對進行模型訓練
from sklearn import svm
# 創建SVC/Support Vector Classification/支持向量機分類器模型
svc_model = svm.SVC(gamma="auto", C=10)
# 將資料擬合到SVC模型中,此處用到了標簽值y_train,是有監督學習
svc_model.fit(x_train, y_train)
score = svc_model.score(x_test,y_test)
y_predict = svc_model.predict(x_test)
print("直接計算準確率:\n",score)
直接計算準確率:
0.9862579281183932
from sklearn.metrics import classification_report
target_names = [str(i) for i in range(0,10)]
print(classification_report(y_test, y_predict, target_names=target_names))
precision recall f1-score support
0 1.00 1.00 1.00 87
1 0.98 0.99 0.98 97
2 0.99 0.99 0.99 92
3 0.99 0.94 0.96 85
4 0.98 1.00 0.99 114
5 0.98 1.00 0.99 108
6 0.99 0.99 0.99 87
7 0.99 0.99 0.99 96
8 1.00 0.98 0.99 91
9 0.97 0.98 0.97 89
accuracy 0.99 946
macro avg 0.99 0.99 0.99 946
weighted avg 0.99 0.99 0.99 946
def SVM(C):
# 創建SVC/Support Vector Classification/支持向量機分類器模型
svc_model = svm.SVC( C=C)
# 將資料擬合到SVC模型中,此處用到了標簽值y_train,是有監督學習
svc_model.fit(x_train, y_train)
score = svc_model.score(x_test,y_test)
y_predict = svc_model.predict(x_test)
print("超引數C="+str(C)+"時,模型的正確率:"+str(score))
return score
L2 = []
c = np.logspace(-5,5,11)
for i in c:
L2.append(SVM(i))
超引數C=1e-05時,模型的正確率:0.09408033826638477
超引數C=0.0001時,模型的正確率:0.09408033826638477
超引數C=0.001時,模型的正確率:0.09408033826638477
超引數C=0.01時,模型的正確率:0.09513742071881606
超引數C=0.1時,模型的正確率:0.952431289640592
超引數C=1.0時,模型的正確率:0.985200845665962
超引數C=10.0時,模型的正確率:0.9904862579281184
超引數C=100.0時,模型的正確率:0.9904862579281184
超引數C=1000.0時,模型的正確率:0.9904862579281184
超引數C=10000.0時,模型的正確率:0.9904862579281184
超引數C=100000.0時,模型的正確率:0.9904862579281184
繪制圖形

模型小結
支持向量機,有大量的核函式可以使用,從而可以很靈活的來解決各種非線性的分類回歸問題,樣本量不是海量資料的時候,分類準確率高,泛化能力強,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/237658.html
標籤:python
上一篇:用Python爬取京東手機評論
下一篇:1-數字與字串
