SVM算法實(shí)現(xiàn)光學(xué)字符識(shí)別
OCR (Optical Character Recognition,光學(xué)字符識(shí)別)是指電子設(shè)備(例如掃描儀或數(shù)碼相機(jī))檢查紙上打印的字符,通過(guò)檢測(cè)暗、亮的模式確定其形狀,然后用字符識(shí)別方法將形狀翻譯成計(jì)算機(jī)字符的過(guò)程;即,針對(duì)印刷體字符,采用光學(xué)的方式將紙質(zhì)文檔中的文字轉(zhuǎn)換成為黑白點(diǎn)陣的圖像文件,并通過(guò)字符識(shí)別模型將圖像中的文字處理成文本格式。
光學(xué)字符識(shí)別是OCR的核心,然而對(duì)于許多類型的機(jī)器學(xué)習(xí)算法來(lái)說(shuō),這種圖像處理都是一項(xiàng)艱巨的任務(wù)。將像素模式連接到更高概念的關(guān)系是極其復(fù)雜的,而且很難定義。
例如,讓一個(gè)人識(shí)別一張面孔、一只貓或字母A是容易的,但用嚴(yán)格的規(guī)則來(lái)定義這些模式是很困難的。此外,圖像數(shù)據(jù)往往是噪聲數(shù)據(jù),對(duì)于光學(xué)字符圖像,燈光、定位和對(duì)象的位置都能影響最終的圖像數(shù)據(jù)。
支持向量機(jī)非常適合處理圖像數(shù)據(jù),它能夠?qū)W習(xí)復(fù)雜的圖案而不需要對(duì)噪聲數(shù)據(jù)過(guò)度敏感,能夠以較高的準(zhǔn)確度識(shí)別光學(xué)圖案。
1
數(shù)據(jù)來(lái)源
本博文中,將使用UCI公開(kāi)的光學(xué)字符識(shí)別數(shù)據(jù)集(http://archive.ics.uci.edu/ml/datasets/Letter+Recognition),利用支持向量機(jī)(SVM)來(lái)構(gòu)建光學(xué)字符識(shí)別模型。
該數(shù)據(jù)集包含了26個(gè)英文大寫(xiě)字母的20000個(gè)樣本。每一個(gè)樣本代表光學(xué)圖像中的一個(gè)矩形區(qū)域,該區(qū)域只包含單一字符。每一個(gè)樣本包含16個(gè)自變量和letter目標(biāo)變量,letter指示當(dāng)前樣本是哪一個(gè)字母。每一個(gè)特征變量的具體含義如下:
letter 字符 (取值為A,B,...,Z)
x-box 字符所在矩形區(qū)域的水平位置
y-box 字符所在矩形區(qū)域的豎直位置
width 矩形區(qū)域的寬度
high 矩形區(qū)域的高度
onpix 矩陣區(qū)域的黑色像素?cái)?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í)別數(shù)據(jù)集中包含16個(gè)特征變量,這些變量用字符矩形區(qū)域的水平位置和豎直位置、黑色像素比例、黑色像素的平均水平和豎直位置來(lái)度量一個(gè)字符。
首先,使用pandas中的read_csv()函數(shù)將數(shù)據(jù)導(dǎo)入,實(shí)現(xiàn)代碼如下所示:
import pandas as pdletters = pd.read_csv("./input/letterecognition.csv")letters.head(10)
前10行數(shù)據(jù)格式如下所示:
接下來(lái)使用pandas中Series的value_counts()函數(shù),觀察數(shù)據(jù)集中每一種字符的數(shù)量分布。
sort_index()函數(shù)可以讓結(jié)果按照字母排序展示結(jié)果,實(shí)現(xiàn)代碼如下所示:
letters["letter"].value_counts().sort_index()效果如下所示:
可見(jiàn),各個(gè)字符的樣本數(shù)量分布相對(duì)均衡。
現(xiàn)在,進(jìn)一步觀察每一個(gè)自變量的取值分布,實(shí)現(xiàn)代碼如下所示:
letters.iloc[:,1:].describe()數(shù)據(jù)取值分布(部分)如下所示:
觀察發(fā)現(xiàn)16個(gè)自變量的取值范圍都在0~15之間,因此對(duì)于該數(shù)據(jù)集不需要對(duì)變量進(jìn)行標(biāo)準(zhǔn)化操作。
此外,數(shù)據(jù)集作者已經(jīng)將樣本隨機(jī)排列,所以也不需要我們對(duì)數(shù)據(jù)進(jìn)行隨機(jī)打散。此處,直接取前14000個(gè)樣本(70%)作為訓(xùn)練集,后6000個(gè)樣本(30%)作為測(cè)試集,實(shí)現(xiàn)代碼如下所示:
letters_train = letters.iloc[0:14000,]letters_test = letters.iloc[14000:20000,]
3
模型訓(xùn)練
接下來(lái)使用sklearn.svm包中的相關(guān)類來(lái)實(shí)現(xiàn)來(lái)構(gòu)建基于支持向量機(jī)的光學(xué)字符識(shí)別模型。
在sklearn.svm包中,有三個(gè)類均實(shí)現(xiàn)了支持向量機(jī)算法:SVC, NuSVC 和 LinearSVC。SVC 和 NuSVC接受的參數(shù)有細(xì)微差別,且底層的數(shù)學(xué)形式不一樣。而 LinearSVC 則是使用簡(jiǎn)單的線性核函數(shù),其實(shí)現(xiàn)基于liblinear (https://www.csie.ntu.edu.tw/~cjlin/liblinear/), 對(duì)于大規(guī)模的樣本訓(xùn)練速度會(huì)更快。這三個(gè)支持向量機(jī)的具體介紹參考sklearn官方文檔:http://scikit-learn.org/stable/modules/svm.html。
本案例中,選用 SVC 來(lái)進(jìn)行模型構(gòu)建。SVC 有兩個(gè)主要的參數(shù)可以設(shè)置:核函數(shù)參數(shù) kernel 和約束懲罰參數(shù)C。核函數(shù)參數(shù) kernel的常用取值及其對(duì)應(yīng)含義如下:
"linear":線性核函數(shù)
"poly":多項(xiàng)式核函數(shù)
"rbf":徑向基核函數(shù)
"sigmoid":sigmoid核函數(shù)
約束懲罰參數(shù)C為對(duì)超過(guò)約束條件的樣本的懲罰項(xiàng)。C值越大,懲罰越大,支持向量機(jī)的決策邊界越窄。
現(xiàn)在,可以使用訓(xùn)練集構(gòu)建分類模型了,選用最簡(jiǎn)單的線性核函數(shù),C采用默認(rèn)值1。實(shí)現(xiàn)代碼如下所示:
from sklearn.svm import SVCletter_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
模型性能評(píng)估
接下來(lái),使用predict()函數(shù)得到上一節(jié)訓(xùn)練的支持向量機(jī)模型在測(cè)試集合上的預(yù)測(cè)結(jié)果,然后使用 sklearn.metrics中的相關(guān)函數(shù)對(duì)模型的性能進(jìn)行評(píng)估,實(shí)現(xiàn)代碼如下所示:
from sklearn import metricsletters_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 0B 0 181 0 4 1 0 1 2 1 1 ... 0 10 4 0C 1 0 169 0 8 0 7 0 0 0 ... 0 0 0 0D 1 9 0 228 0 1 1 2 0 1 ... 0 0 0 0E 0 2 5 0 197 2 11 0 0 0 ... 1 1 1 5F 0 1 3 1 3 213 1 2 2 3 ... 0 0 0 4G 0 2 14 2 1 4 177 2 0 0 ... 9 3 5 0H 1 4 2 12 0 5 4 147 0 1 ... 3 9 0 1I 0 1 2 4 0 7 0 0 208 12 ... 0 0 2 0J 2 0 0 2 0 2 0 3 11 190 ... 0 0 2 0K 0 0 2 5 4 0 1 5 0 0 ... 0 12 0 0L 0 0 5 5 6 0 3 2 0 0 ... 4 1 3 1M 1 3 0 0 0 0 0 3 0 0 ... 0 2 0 0N 1 0 0 7 0 0 0 10 0 0 ... 0 2 0 0O 3 0 3 7 0 0 2 26 0 1 ... 5 1 0 0P 0 2 0 3 0 25 5 0 1 1 ... 1 1 0 0Q 5 5 0 1 7 1 14 3 0 4 ... 190 1 13 0R 0 11 0 4 0 0 2 6 0 0 ... 0 203 0 0S 1 8 0 1 10 7 7 0 4 1 ... 9 1 160 3T 1 0 0 0 0 3 2 5 0 0 ... 0 1 2 204U 1 0 0 1 0 0 0 1 0 0 ... 0 0 0 1V 0 2 0 0 0 2 0 4 0 0 ... 0 1 0 0W 1 0 0 0 0 0 0 0 0 0 ... 0 0 0 0X 0 1 0 5 5 1 1 0 6 3 ... 0 0 2 2Y 0 0 0 3 0 4 0 3 1 0 ... 2 0 0 5Z 1 0 0 1 4 1 0 0 1 9 ... 0 0 18 3U V W X Y ZA 2 0 0 0 3 3B 0 0 0 1 0 0C 4 0 0 0 0 0D 3 0 0 0 0 0E 0 0 0 2 0 2F 0 0 0 0 1 0G 0 6 1 0 0 0H 2 3 0 2 0 0I 0 0 0 4 0 3J 0 0 0 0 0 2K 2 0 0 4 0 0L 0 0 0 6 0 0M 1 0 4 0 0 0N 1 2 0 0 0 0O 3 1 4 1 0 0P 1 0 0 0 5 0Q 0 1 0 0 0 0R 0 1 0 1 0 0S 0 0 0 2 1 20T 0 0 0 0 3 3U 228 0 6 0 0 0V 0 193 6 0 1 0W 2 2 199 0 0 0X 1 0 0 193 1 0Y 0 4 1 1 196 0Z 0 0 0 1 0 196rows x 26 columns]
上述混淆矩陣中對(duì)角線的元素表示模型正確預(yù)測(cè)數(shù),對(duì)角元素之和表示模型整體預(yù)測(cè)正確的樣本數(shù)。
而非對(duì)角線元素上的值則可以反映模型在哪些類的預(yù)測(cè)上容易犯錯(cuò),例如第P行第F列的取值為25,說(shuō)明模型有25次將“P”字符錯(cuò)誤地識(shí)別為“F”字符。直觀來(lái)看,“P”和“F”相似度比較高,對(duì)它們的區(qū)分也更具有挑戰(zhàn)性?,F(xiàn)在,來(lái)通過(guò)這個(gè)來(lái)計(jì)算模型在測(cè)試集中的預(yù)測(cè)正確率。代碼如下所示:
agreement = lettters_test["letter"] == letters_predprint(agreement.value_counts())print("Accuracy:", metrics.accuracy_score(lettters_test["letter"], letters_pred))
預(yù)測(cè)正確率,效果如下所示:
可見(jiàn),初步模型在6000個(gè)測(cè)試樣本中,正確預(yù)測(cè)5068個(gè),整體正確率(Accuaray)為84.47%。
5
模型性能提升
對(duì)于支持向量機(jī),有兩個(gè)主要的參數(shù)能夠影響模型的性能:一是核函數(shù)的選取,二是懲罰參數(shù)C的選擇。下面,期望通過(guò)分別嘗試這兩個(gè)參數(shù)來(lái)進(jìn)一步改善模型的預(yù)測(cè)性能。
5.1、核函數(shù)的選取
在 SVC 中,核函數(shù)參數(shù)kernel可選值為"rbf"(徑向基核函數(shù))、“poly”(多項(xiàng)式核函數(shù))、"sigmoid"(sigmoid核函數(shù))和"linear"(線性核函數(shù))。我們的初始模型選取的是線性核函數(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.971166666667kernel = poly , Accuracy: 0.943166666667kernel = sigmoid , Accuracy: 0.0376666666667
從結(jié)果可以看到,當(dāng)選取RBF核函數(shù)時(shí):
模型正確率由84.47%提高到97.12%
多項(xiàng)式核函數(shù)下模型正確率為94.32%
sigmoid核函數(shù)下模型的正確率只有3.77%
5.2、懲罰參數(shù)C的選取
我們將分別測(cè)試 ??=0.01,0.1,1,10,100C=0.01,0.1,1,10,100時(shí)字符識(shí)別模型正確率的變化。
核函數(shù)選取徑向基核函數(shù)(即"rbf"),實(shí)現(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.059C = 0.1 , Accuracy: 0.886333333333C = 1 , Accuracy: 0.971166666667C = 10 , Accuracy: 0.976166666667C = 100 , Accuracy: 0.976333333333
可見(jiàn),當(dāng)懲罰參數(shù)C設(shè)置為10和100時(shí),模型正確率進(jìn)一步提升,分別達(dá)到97.62%和97.63%。
往期推薦

