目錄
1、資料來源
2、資料預處理
3、模型訓練
4、模型性能評估
5、模型性能提升
5.1、核函式的選取
5.2、懲罰引數C的選取
OCR (Optical Character Recognition,光學字符識別)是指電子設備(例如掃描儀或數碼相機)檢查紙上列印的字符,通過檢測暗、亮的模式確定其形狀,然后用字符識別方法將形狀翻譯成計算機字符的程序;即,針對印刷體字符,采用光學的方式將紙質檔案中的文字轉換成為黑白點陣的影像檔案,并通過字符識別模型將影像中的文字處理成文本格式,
光學字符識別是OCR的核心,然而對于許多型別的機器學習演算法來說,這種影像處理都是一項艱巨的任務, 將像素模式連接到更高概念的關系是極其復雜的,而且很難定義, 例如,讓一個人識別一張面孔、一只貓或字母A是容易的,但用嚴格的規則來定義這些模式是很困難的, 此外,影像資料往往是噪聲資料,對于光學字符影像,燈光、定位和物件的位置都能影響最終的影像資料,
支持向量機非常適合處理影像資料,它能夠學習復雜的圖案而不需要對噪聲資料過度敏感,能夠以較高的準確度識別光學圖案,
1、資料來源
本博文中,將使用UCI公開的光學字符識別資料集(http://archive.ics.uci.edu/ml/datasets/Letter+Recognition),利用支持向量機(SVM)來構建光學字符識別模型,
該資料集包含了26個英文大寫字母的20000個樣本, 每一個樣本代表光學影像中的一個矩形區域,該區域只包含單一字符, 每一個樣本包含16個自變數和letter目標變數,letter指示當前樣本是哪一個字母,每一個特征變數的具體含義如下:
- letter 字符 (取值為A,B,...,Z)
- x-box 字符所在矩形區域的水平位置
- y-box 字符所在矩形區域的豎直位置
- width 矩形區域的寬度
- high 矩形區域的高度
- onpix 矩陣區域的黑色像素數
- x-bar 矩形區域內黑色像素的平均x值
- y-bar 矩形區域內黑色像素的平均y值
- x2bar x平均方差
- y2bar y平均方差
- xybar x和y的平均相關性
- x2ybr x * x * y 均值
- xy2br x * y * y 均值
- x-ege 從左到右的邊緣數目
- xegvy x邊緣與y的相關性
- y-ege 從下到上的邊緣數目
- yegvx y邊緣與x的相關性
2、資料預處理
光學字符識別資料集中包含16個特征變數,這些變數用字符矩形區域的水平位置和豎直位置、黑色像素比例、黑色像素的平均水平和豎直位置來度量一個字符,
首先,使用pandas中的read_csv()函式將資料匯入,實作代碼如下所示:
import pandas as pd
letters = pd.read_csv("./input/letterecognition.csv")
letters.head(10)
前10行資料格式如下所示:

接下來使用pandas中Series的value_counts()函式,觀察資料集中每一種字符的數量分布,
sort_index()函式可以讓結果按照字母排序展示結果,實作代碼如下所示:
letters["letter"].value_counts().sort_index()
效果如下所示:

可見,各個字符的樣本數量分布相對均衡,
現在,進一步觀察每一個自變數的取值分布,實作代碼如下所示:
letters.iloc[:,1:].describe()
資料取值分布如下所示:
| xbox | ybox | width | height | onpix | xbar | ybar | x2bar | y2bar | xybar | x2ybar | xy2bar | xedge | xedgey | yedge | yedgex | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 20000.000000 | 20000.000000 | 20000.000000 | 20000.00000 | 20000.000000 | 20000.000000 | 20000.000000 | 20000.000000 | 20000.000000 | 20000.000000 | 20000.00000 | 20000.000000 | 20000.000000 | 20000.000000 | 20000.000000 | 20000.00000 |
| mean | 4.023550 | 7.035500 | 5.121850 | 5.37245 | 3.505850 | 6.897600 | 7.500450 | 4.628600 | 5.178650 | 8.282050 | 6.45400 | 7.929000 | 3.046100 | 8.338850 | 3.691750 | 7.80120 |
| std | 1.913212 | 3.304555 | 2.014573 | 2.26139 | 2.190458 | 2.026035 | 2.325354 | 2.699968 | 2.380823 | 2.488475 | 2.63107 | 2.080619 | 2.332541 | 1.546722 | 2.567073 | 1.61747 |
| min | 0.000000 | 0.000000 | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.00000 |
| 25% | 3.000000 | 5.000000 | 4.000000 | 4.00000 | 2.000000 | 6.000000 | 6.000000 | 3.000000 | 4.000000 | 7.000000 | 5.00000 | 7.000000 | 1.000000 | 8.000000 | 2.000000 | 7.00000 |
| 50% | 4.000000 | 7.000000 | 5.000000 | 6.00000 | 3.000000 | 7.000000 | 7.000000 | 4.000000 | 5.000000 | 8.000000 | 6.00000 | 8.000000 | 3.000000 | 8.000000 | 3.000000 | 8.00000 |
| 75% | 5.000000 | 9.000000 | 6.000000 | 7.00000 | 5.000000 | 8.000000 | 9.000000 | 6.000000 | 7.000000 | 10.000000 | 8.00000 | 9.000000 | 4.000000 | 9.000000 | 5.000000 | 9.00000 |
| max | 15.000000 | 15.000000 | 15.000000 | 15.00000 | 15.000000 | 15.000000 | 15.000000 | 15.000000 | 15.000000 | 15.000000 | 15.00000 | 15.000000 | 15.000000 | 15.000000 | 15.000000 | 15.00000 |
觀察發現16個自變數的取值范圍都在0~15之間,因此對于該資料集不需要對變數進行標準化操作,
此外,資料集作者已經將樣本隨機排列,所以也不需要我們對資料進行隨機打散, 此處,直接取前14000個樣本(70%)作為訓練集,后6000個樣本(30%)作為測驗集,實作代碼如下所示:
letters_train = letters.iloc[0:14000,]
letters_test = letters.iloc[14000:20000,]
3、模型訓練
接下來使用sklearn.svm包中的相關類來實作來構建基于支持向量機的光學字符識別模型,
在sklearn.svm包中,有三個類均實作了支持向量機演算法:SVC, NuSVC 和 LinearSVC, SVC 和 NuSVC接受的引數有細微差別,且底層的數學形式不一樣, 而 LinearSVC 則是使用簡單的線性核函式,其實作基于liblinear (https://www.csie.ntu.edu.tw/~cjlin/liblinear/), 對于大規模的樣本訓練速度會更快, 這三個支持向量機的具體介紹參考sklearn官方檔案:http://scikit-learn.org/stable/modules/svm.html,
本案例中,選用 SVC 來進行模型構建, SVC 有兩個主要的引數可以設定:核函式引數 kernel 和約束懲罰引數C, 核函式引數 kernel的常用取值及其對應含義如下:
- "linear":線性核函式
- "poly":多項式核函式
- "rbf":徑向基核函式
- "sigmoid": sigmoid核函式
約束懲罰引數C為對超過約束條件的樣本的懲罰項,C值越大,懲罰越大,支持向量機的決策邊界越窄,
現在,可以使用訓練集構建分類模型了,選用最簡單的線性核函式,C采用默認值1,實作代碼如下所示:
from sklearn.svm import SVC
letter_recognition_model = SVC(C = 1, kernel = "linear")
letter_recognition_model.fit(letters_train.iloc[:,1:],letters_train['letter'])
設定成功后,SVC配置引數效果如下所示:
SVC(C=1, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=None, degree=3, gamma='auto', kernel='linear',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
4、模型性能評估
接下來,使用predict()函式得到上一節訓練的支持向量機模型在測驗集合上的預測結果,然后使用 sklearn.metrics中的相關函式對模型的性能進行評估,實作代碼如下所示:
from sklearn import metrics
letters_pred = letter_recognition_model.predict(letters_test.iloc[:,1:])
print(metrics.classification_report(lettters_test["letter"], letters_pred))
print(pd.DataFrame(metrics.confusion_matrix(lettters_test["letter"], letters_pred),\
columns = letters["letter"].value_counts().sort_index().index,\
index = letters["letter"].value_counts().sort_index().index))
效果如下所示:
precision recall f1-score support
A 0.92 0.92 0.92 245
B 0.78 0.87 0.82 207
C 0.82 0.84 0.83 202
D 0.77 0.91 0.83 251
E 0.80 0.86 0.83 230
F 0.77 0.89 0.82 240
G 0.73 0.75 0.74 235
H 0.65 0.70 0.67 210
I 0.89 0.86 0.87 243
J 0.83 0.88 0.86 216
K 0.79 0.84 0.81 214
L 0.95 0.86 0.90 250
M 0.89 0.94 0.92 224
N 0.95 0.88 0.91 246
O 0.87 0.71 0.78 216
P 0.92 0.80 0.86 246
Q 0.85 0.75 0.80 252
R 0.81 0.84 0.82 242
S 0.75 0.67 0.71 240
T 0.89 0.90 0.90 226
U 0.91 0.92 0.92 248
V 0.91 0.91 0.91 212
W 0.90 0.92 0.91 216
X 0.89 0.84 0.86 230
Y 0.93 0.88 0.90 223
Z 0.86 0.83 0.84 236
avg / total 0.85 0.84 0.84 6000
A B C D E F G H I J ... Q R S T \
A 225 1 0 2 0 0 2 0 0 1 ... 0 2 1 0
B 0 181 0 4 1 0 1 2 1 1 ... 0 10 4 0
C 1 0 169 0 8 0 7 0 0 0 ... 0 0 0 0
D 1 9 0 228 0 1 1 2 0 1 ... 0 0 0 0
E 0 2 5 0 197 2 11 0 0 0 ... 1 1 1 5
F 0 1 3 1 3 213 1 2 2 3 ... 0 0 0 4
G 0 2 14 2 1 4 177 2 0 0 ... 9 3 5 0
H 1 4 2 12 0 5 4 147 0 1 ... 3 9 0 1
I 0 1 2 4 0 7 0 0 208 12 ... 0 0 2 0
J 2 0 0 2 0 2 0 3 11 190 ... 0 0 2 0
K 0 0 2 5 4 0 1 5 0 0 ... 0 12 0 0
L 0 0 5 5 6 0 3 2 0 0 ... 4 1 3 1
M 1 3 0 0 0 0 0 3 0 0 ... 0 2 0 0
N 1 0 0 7 0 0 0 10 0 0 ... 0 2 0 0
O 3 0 3 7 0 0 2 26 0 1 ... 5 1 0 0
P 0 2 0 3 0 25 5 0 1 1 ... 1 1 0 0
Q 5 5 0 1 7 1 14 3 0 4 ... 190 1 13 0
R 0 11 0 4 0 0 2 6 0 0 ... 0 203 0 0
S 1 8 0 1 10 7 7 0 4 1 ... 9 1 160 3
T 1 0 0 0 0 3 2 5 0 0 ... 0 1 2 204
U 1 0 0 1 0 0 0 1 0 0 ... 0 0 0 1
V 0 2 0 0 0 2 0 4 0 0 ... 0 1 0 0
W 1 0 0 0 0 0 0 0 0 0 ... 0 0 0 0
X 0 1 0 5 5 1 1 0 6 3 ... 0 0 2 2
Y 0 0 0 3 0 4 0 3 1 0 ... 2 0 0 5
Z 1 0 0 1 4 1 0 0 1 9 ... 0 0 18 3
U V W X Y Z
A 2 0 0 0 3 3
B 0 0 0 1 0 0
C 4 0 0 0 0 0
D 3 0 0 0 0 0
E 0 0 0 2 0 2
F 0 0 0 0 1 0
G 0 6 1 0 0 0
H 2 3 0 2 0 0
I 0 0 0 4 0 3
J 0 0 0 0 0 2
K 2 0 0 4 0 0
L 0 0 0 6 0 0
M 1 0 4 0 0 0
N 1 2 0 0 0 0
O 3 1 4 1 0 0
P 1 0 0 0 5 0
Q 0 1 0 0 0 0
R 0 1 0 1 0 0
S 0 0 0 2 1 20
T 0 0 0 0 3 3
U 228 0 6 0 0 0
V 0 193 6 0 1 0
W 2 2 199 0 0 0
X 1 0 0 193 1 0
Y 0 4 1 1 196 0
Z 0 0 0 1 0 196
[26 rows x 26 columns]
上述混淆矩陣中對角線的元素表示模型正確預測數,對角元素之和表示模型整體預測正確的樣本數,
而非對角線元素上的值則可以反映模型在哪些類的預測上容易犯錯,例如第P行第F列的取值為25,說明模型有25次將“P”字符錯誤地識別為“F”字符,直觀來看,“P”和“F”相似度比較高,對它們的區分也更具有挑戰性, 現在,來通過這個來計算模型在測驗集中的預測正確率,代碼如下所示:
agreement = lettters_test["letter"] == letters_pred
print(agreement.value_counts())
print("Accuracy:", metrics.accuracy_score(lettters_test["letter"], letters_pred))
預測正確率,效果如下所示:
True 5068
False 932
dtype: int64
Accuracy: 0.844666666667
可見,初步模型在6000個測驗樣本中,正確預測5068個,整體正確率(Accuaray)為84.47%,
5、模型性能提升
對于支持向量機,有兩個主要的引數能夠影響模型的性能:一是核函式的選取,二是懲罰引數C的選擇, 下面,期望通過分別嘗試這兩個引數來進一步改善模型的預測性能,
5.1、核函式的選取
在 SVC 中,核函式引數kernel可選值為"rbf"(徑向基核函式)、“poly”(多項式核函式)、"sigmoid"(sigmoid核函式)和"linear"(線性核函式),我們的初始模型選取的是線性核函式,下面我們觀察在其他三種核函式下模型正確率的改變,實作代碼如下所示:
kernels = ["rbf","poly","sigmoid"]
for kernel in kernels:
letters_model = SVC(C = 1, kernel = kernel)
letters_model.fit(letters_train.iloc[:,1:],letters_train['letter'])
letters_pred = letters_model.predict(letters_test.iloc[:,1:])
print("kernel = ", kernel , ", Accuracy:",\
metrics.accuracy_score(lettters_test["letter"], letters_pred))
效果如下所示:
kernel = rbf , Accuracy: 0.971166666667
kernel = poly , Accuracy: 0.943166666667
kernel = sigmoid , Accuracy: 0.0376666666667
從結果可以看到,當選取RBF核函式時:
- 模型正確率由84.47%提高到97.12%
- 多項式核函式下模型正確率為94.32%
- sigmoid核函式下模型的正確率只有3.77%
5.2、懲罰引數C的選取
我們將分別測驗 𝐶=0.01,0.1,1,10,100C=0.01,0.1,1,10,100時字符識別模型正確率的變化,
核函式選取徑向基核函式(即"rbf"),實作代碼如下所示:
c_list = [0.01, 0.1, 1, 10, 100]
for C in c_list:
letters_model = SVC(C = C, kernel = "rbf")
letters_model.fit(letters_train.iloc[:,1:],letters_train['letter'])
letters_pred = letters_model.predict(letters_test.iloc[:,1:])
print("C = ", C , ", Accuracy:",\
metrics.accuracy_score(lettters_test["letter"], letters_pred))
效果如下所示:
C = 0.01 , Accuracy: 0.059
C = 0.1 , Accuracy: 0.886333333333
C = 1 , Accuracy: 0.971166666667
C = 10 , Accuracy: 0.976166666667
C = 100 , Accuracy: 0.976333333333
可見,當懲罰引數C設定為10和100時,模型正確率進一步提升,分別達到97.62%和97.63%,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/272854.html
標籤:其他
上一篇:從零開始搭建自己的大資料環境---zookeeper篇
下一篇:MySQL資料庫與資料表的創建
