SVM算法实现光学字符识别
目錄
1、數(shù)據(jù)來源
2、數(shù)據(jù)預(yù)處理
3、模型訓(xùn)練
4、模型性能評估
5、模型性能提升
5.1、核函數(shù)的選取
5.2、懲罰參數(shù)C的選取
OCR (Optical Character Recognition,光學(xué)字符識別)是指電子設(shè)備(例如掃描儀或數(shù)碼相機)檢查紙上打印的字符,通過檢測暗、亮的模式確定其形狀,然后用字符識別方法將形狀翻譯成計算機字符的過程;即,針對印刷體字符,采用光學(xué)的方式將紙質(zhì)文檔中的文字轉(zhuǎn)換成為黑白點陣的圖像文件,并通過字符識別模型將圖像中的文字處理成文本格式。
光學(xué)字符識別是OCR的核心,然而對于許多類型的機器學(xué)習(xí)算法來說,這種圖像處理都是一項艱巨的任務(wù)。 將像素模式連接到更高概念的關(guān)系是極其復(fù)雜的,而且很難定義。 例如,讓一個人識別一張面孔、一只貓或字母A是容易的,但用嚴(yán)格的規(guī)則來定義這些模式是很困難的。 此外,圖像數(shù)據(jù)往往是噪聲數(shù)據(jù),對于光學(xué)字符圖像,燈光、定位和對象的位置都能影響最終的圖像數(shù)據(jù)。
支持向量機非常適合處理圖像數(shù)據(jù),它能夠?qū)W習(xí)復(fù)雜的圖案而不需要對噪聲數(shù)據(jù)過度敏感,能夠以較高的準(zhǔn)確度識別光學(xué)圖案。
1、數(shù)據(jù)來源
本博文中,將使用UCI公開的光學(xué)字符識別數(shù)據(jù)集(http://archive.ics.uci.edu/ml/datasets/Letter+Recognition),利用支持向量機(SVM)來構(gòu)建光學(xué)字符識別模型。
該數(shù)據(jù)集包含了26個英文大寫字母的20000個樣本。 每一個樣本代表光學(xué)圖像中的一個矩形區(qū)域,該區(qū)域只包含單一字符。 每一個樣本包含16個自變量和letter目標(biāo)變量,letter指示當(dāng)前樣本是哪一個字母。每一個特征變量的具體含義如下:
- letter 字符 (取值為A,B,...,Z)
- x-box 字符所在矩形區(qū)域的水平位置
- y-box 字符所在矩形區(qū)域的豎直位置
- width 矩形區(qū)域的寬度
- high 矩形區(qū)域的高度
- onpix 矩陣區(qū)域的黑色像素數(shù)
- x-bar 矩形區(qū)域內(nèi)黑色像素的平均x值
- y-bar 矩形區(qū)域內(nèi)黑色像素的平均y值
- x2bar x平均方差
- y2bar y平均方差
- xybar x和y的平均相關(guān)性
- x2ybr x * x * y 均值
- xy2br x * y * y 均值
- x-ege 從左到右的邊緣數(shù)目
- xegvy x邊緣與y的相關(guān)性
- y-ege 從下到上的邊緣數(shù)目
- yegvx y邊緣與x的相關(guān)性
2、數(shù)據(jù)預(yù)處理
光學(xué)字符識別數(shù)據(jù)集中包含16個特征變量,這些變量用字符矩形區(qū)域的水平位置和豎直位置、黑色像素比例、黑色像素的平均水平和豎直位置來度量一個字符。
首先,使用pandas中的read_csv()函數(shù)將數(shù)據(jù)導(dǎo)入,實現(xiàn)代碼如下所示:
import pandas as pd
letters = pd.read_csv("./input/letterecognition.csv")
letters.head(10)
前10行數(shù)據(jù)格式如下所示:
接下來使用pandas中Series的value_counts()函數(shù),觀察數(shù)據(jù)集中每一種字符的數(shù)量分布。
sort_index()函數(shù)可以讓結(jié)果按照字母排序展示結(jié)果,實現(xiàn)代碼如下所示:
letters["letter"].value_counts().sort_index()
效果如下所示:
可見,各個字符的樣本數(shù)量分布相對均衡。
現(xiàn)在,進一步觀察每一個自變量的取值分布,實現(xiàn)代碼如下所示:
letters.iloc[:,1:].describe()
數(shù)據(jù)取值分布如下所示:?
| ? | 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 |
觀察發(fā)現(xiàn)16個自變量的取值范圍都在0~15之間,因此對于該數(shù)據(jù)集不需要對變量進行標(biāo)準(zhǔn)化操作。
此外,數(shù)據(jù)集作者已經(jīng)將樣本隨機排列,所以也不需要我們對數(shù)據(jù)進行隨機打散。 此處,直接取前14000個樣本(70%)作為訓(xùn)練集,后6000個樣本(30%)作為測試集,實現(xiàn)代碼如下所示:
letters_train = letters.iloc[0:14000,]
letters_test = letters.iloc[14000:20000,]
3、模型訓(xùn)練
接下來使用sklearn.svm包中的相關(guān)類來實現(xiàn)來構(gòu)建基于支持向量機的光學(xué)字符識別模型。
在sklearn.svm包中,有三個類均實現(xiàn)了支持向量機算法:SVC, NuSVC 和 LinearSVC。 SVC 和 NuSVC接受的參數(shù)有細(xì)微差別,且底層的數(shù)學(xué)形式不一樣。 而 LinearSVC 則是使用簡單的線性核函數(shù),其實現(xiàn)基于liblinear (https://www.csie.ntu.edu.tw/~cjlin/liblinear/), 對于大規(guī)模的樣本訓(xùn)練速度會更快。 這三個支持向量機的具體介紹參考sklearn官方文檔:http://scikit-learn.org/stable/modules/svm.html。
本案例中,選用 SVC 來進行模型構(gòu)建。 SVC 有兩個主要的參數(shù)可以設(shè)置:核函數(shù)參數(shù) kernel 和約束懲罰參數(shù)C。 核函數(shù)參數(shù) kernel的常用取值及其對應(yīng)含義如下:
- "linear":線性核函數(shù)
- "poly":多項式核函數(shù)
- "rbf":徑向基核函數(shù)
- "sigmoid": sigmoid核函數(shù)
約束懲罰參數(shù)C為對超過約束條件的樣本的懲罰項。C值越大,懲罰越大,支持向量機的決策邊界越窄。
現(xiàn)在,可以使用訓(xùn)練集構(gòu)建分類模型了,選用最簡單的線性核函數(shù),C采用默認(rèn)值1。實現(xiàn)代碼如下所示:
from sklearn.svm import SVC
letter_recognition_model = SVC(C = 1, kernel = "linear")
letter_recognition_model.fit(letters_train.iloc[:,1:],letters_train['letter'])
設(shè)置成功后,SVC配置參數(shù)效果如下所示:
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()函數(shù)得到上一節(jié)訓(xùn)練的支持向量機模型在測試集合上的預(yù)測結(jié)果,然后使用 sklearn.metrics中的相關(guān)函數(shù)對模型的性能進行評估,實現(xiàn)代碼如下所示:
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 supportA 0.92 0.92 0.92 245B 0.78 0.87 0.82 207C 0.82 0.84 0.83 202D 0.77 0.91 0.83 251E 0.80 0.86 0.83 230F 0.77 0.89 0.82 240G 0.73 0.75 0.74 235H 0.65 0.70 0.67 210I 0.89 0.86 0.87 243J 0.83 0.88 0.86 216K 0.79 0.84 0.81 214L 0.95 0.86 0.90 250M 0.89 0.94 0.92 224N 0.95 0.88 0.91 246O 0.87 0.71 0.78 216P 0.92 0.80 0.86 246Q 0.85 0.75 0.80 252R 0.81 0.84 0.82 242S 0.75 0.67 0.71 240T 0.89 0.90 0.90 226U 0.91 0.92 0.92 248V 0.91 0.91 0.91 212W 0.90 0.92 0.91 216X 0.89 0.84 0.86 230Y 0.93 0.88 0.90 223Z 0.86 0.83 0.84 236avg / total 0.85 0.84 0.84 6000A 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]
上述混淆矩陣中對角線的元素表示模型正確預(yù)測數(shù),對角元素之和表示模型整體預(yù)測正確的樣本數(shù)。
而非對角線元素上的值則可以反映模型在哪些類的預(yù)測上容易犯錯,例如第P行第F列的取值為25,說明模型有25次將“P”字符錯誤地識別為“F”字符。直觀來看,“P”和“F”相似度比較高,對它們的區(qū)分也更具有挑戰(zhàn)性。 現(xiàn)在,來通過這個來計算模型在測試集中的預(yù)測正確率。代碼如下所示:
agreement = lettters_test["letter"] == letters_pred
print(agreement.value_counts())
print("Accuracy:", metrics.accuracy_score(lettters_test["letter"], letters_pred))
預(yù)測正確率,效果如下所示:
True 5068
False 932
dtype: int64
Accuracy: 0.844666666667
可見,初步模型在6000個測試樣本中,正確預(yù)測5068個,整體正確率(Accuaray)為84.47%。
5、模型性能提升
對于支持向量機,有兩個主要的參數(shù)能夠影響模型的性能:一是核函數(shù)的選取,二是懲罰參數(shù)C的選擇。 下面,期望通過分別嘗試這兩個參數(shù)來進一步改善模型的預(yù)測性能。
5.1、核函數(shù)的選取
在 SVC 中,核函數(shù)參數(shù)kernel可選值為"rbf"(徑向基核函數(shù))、“poly”(多項式核函數(shù))、"sigmoid"(sigmoid核函數(shù))和"linear"(線性核函數(shù))。我們的初始模型選取的是線性核函數(shù),下面我們觀察在其他三種核函數(shù)下模型正確率的改變。實現(xiàn)代碼如下所示:
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
從結(jié)果可以看到,當(dāng)選取RBF核函數(shù)時:
- 模型正確率由84.47%提高到97.12%
- ?多項式核函數(shù)下模型正確率為94.32%
- ?sigmoid核函數(shù)下模型的正確率只有3.77%
5.2、懲罰參數(shù)C的選取
我們將分別測試?𝐶=0.01,0.1,1,10,100C=0.01,0.1,1,10,100時字符識別模型正確率的變化。
核函數(shù)選取徑向基核函數(shù)(即"rbf"),實現(xiàn)代碼如下所示:
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
可見,當(dāng)懲罰參數(shù)C設(shè)置為10和100時,模型正確率進一步提升,分別達(dá)到97.62%和97.63%。
總結(jié)
以上是生活随笔為你收集整理的SVM算法实现光学字符识别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单片机如何从上电复位执行到main函数?
- 下一篇: 大意!6行代码,“报废”5片单片机!