2017年11月20
撰寫了有關(guān)數(shù)字識(shí)別人工智能的課程設(shè)計(jì)論文,包括程序
手寫數(shù)字識(shí)別 摘要 手寫數(shù)字識(shí)別是機(jī)器學(xué)習(xí)領(lǐng)域中一個(gè)經(jīng)典的問題,是一個(gè)看似對人類很簡單卻對程序十分復(fù)雜的問題。很多早期的驗(yàn)證碼就是利用這個(gè)特點(diǎn)來區(qū)分人類和程序行為的。在手寫數(shù)字識(shí)別中,比如,我們要識(shí)別出一個(gè)手寫的“9”,人類可能通過識(shí)別“上半部分一個(gè)圓圈,右下方引出一條豎線”就能進(jìn)行判斷。但用程序表達(dá)就似乎很困難了,你需要考慮非常多的描述方式,考慮非常多的特殊情況。在本文中將從K-近鄰算法(KNN)和一對多的邏輯回歸算法角度進(jìn)行分析。
第1章 K-近鄰算法 最簡單最初級的分類器是將全部的訓(xùn)練數(shù)據(jù)所對應(yīng)的類別都記錄下來,當(dāng)測試對象的屬性和某個(gè)訓(xùn)練對象的屬性完全匹配時(shí),便可以對其進(jìn)行分類。但是怎么可能所有測試對象都會(huì)找到與之完全匹配的訓(xùn)練對象呢,其次就是存在一個(gè)測試對象同時(shí)與多個(gè)訓(xùn)練對象匹配,導(dǎo)致一個(gè)訓(xùn)練對象被分到了多個(gè)類的問題,基于這些問題呢,就產(chǎn)生了KNN。 1.1 K-近鄰基本原理 KNN算法是從訓(xùn)練集中找到和新數(shù)據(jù)最接近的k條記錄,然后根據(jù)它們的主要分類來決定新的數(shù)據(jù)的類別。具體算法步驟如下: ⑴ 算距離:給定測試對象,計(jì)算它與訓(xùn)練集中的每個(gè)對象的距離。什么是合適的距離衡量?距離越近意味著這兩個(gè)點(diǎn)屬于同一類的可能性越大。其中距離的衡量方法包括歐氏距離、夾角余弦等。 ⑵ 找鄰居:圈定距離最近的k個(gè)訓(xùn)練對象,作為測試對象的近鄰。 ⑶ 做分類:根據(jù)這k個(gè)近鄰歸屬的主要類別,來對測試對象分類。分類的判定可以是少數(shù)服從多數(shù),在上個(gè)步驟的k個(gè)訓(xùn)練對象中,哪個(gè)類別的點(diǎn)最多就分為該類。 1.2 matlab算法實(shí)現(xiàn) 本文中的訓(xùn)練樣本為數(shù)字“0~9”,每個(gè)數(shù)字分別有500個(gè)樣本圖片,其中前400個(gè)樣本作為訓(xùn)練集,后100作為測試集。訓(xùn)練集已經(jīng)根據(jù)數(shù)字進(jìn)行分類,并且每個(gè)圖片都經(jīng)過處理轉(zhuǎn)化為20×20的灰度矩陣。為了計(jì)算機(jī)方便計(jì)算,將20×20的灰度矩陣化成1×400的向量形式。 %% 初始化 clear; clc; k = 7; %設(shè)置找近鄰所需對象的數(shù)量 load labels load trainData [m,n] = size(trainData); %% testData a = 4; %a為第a類樣本 b = 56; eval(sprintf('load C:/Users/HP/Documents/%d_%d.txt',a,b)); eval(sprintf('testData = X%d_%d;',a,b)); testData = testData';
|
|
至此我們的測試樣本保存在testData中,接下來運(yùn)行KNN算法。在執(zhí)行KNN算法之前還需要對參數(shù)進(jìn)行進(jìn)行歸一化處理: D = max(trainData,[],2) - min(trainData,[],2); trainData = (trainData-repmat(min(trainData,[],2),1,n))./repmat(D,1,n); testData = (testData - min(testData))./(max(testData)-min(testData)); |
|
之后調(diào)用KNN算法,并顯示判斷結(jié)果: relustLabel = knn(testData,trainData,labels,k); fprintf('the real number in the picture is %d\n',a); fprintf('predict number in the picture is %d\n',relustLabel); |
|
算法具體代碼如下: function relustLabel = knn(inx,data,labels,k) % inx為測試集,data為訓(xùn)練集,labels為訓(xùn)練集標(biāo)簽,k為判斷時(shí)選取的點(diǎn)的個(gè)數(shù) % relustLabel為測試集的標(biāo)簽 [datarow,datacol] = size(data); [inxrow,inxcol] = size(inx); data = repmat(data,1,1,inxrow); inx = repmat(reshape(inx',1,inxcol,inxrow),datarow,1,1); dis = reshape(sum((data-inx).^2,2),datarow,inxrow); [kdis,ind] = sort(dis,1); %¶Ô¾àÀëÅÅÐò ind = ind(1:k,:); for i = 1:inxrow, aa = tabulate(labels(ind(:,i))); [bb,inds] = max(aa(:,2)); relustLabel(i,:) = aa(inds) ; end |
|
程序運(yùn)行結(jié)果如下 1.3 小結(jié) KNN算法簡單易于理解,易于實(shí)現(xiàn),無需參數(shù)估計(jì),無需訓(xùn)練。但它屬于懶惰算法,對測試樣本分類時(shí)的計(jì)算量大,內(nèi)存開銷大,評分慢。可解釋性差。其結(jié)果會(huì)受到K取值的影響。近鄰中可能包含太多的其它類別的點(diǎn)。偶爾會(huì)出現(xiàn)錯(cuò)誤,例如:
第2章 一對多的邏輯回歸 2.1 基本原理 在分類問題中,如果要預(yù)測的變量是一個(gè)離散的值,我們將利用到邏輯回歸的算法。對于一個(gè)二分類問題,我們可以利用Sigmoid函數(shù)來逼近我們的模型。函數(shù)圖像如圖所示: 此處 。Z可以看作是樣本的分界函數(shù),我們要對訓(xùn)練集做的工作就是訓(xùn)練出一條合理的分界函數(shù) 。在測試時(shí),將測試樣本的X帶入得到Z的值,當(dāng)Z大于0時(shí)屬于“1”類,當(dāng)Z小于“0”時(shí)屬于“0”類。但在手寫識(shí)別中,我們的訓(xùn)練樣本一共有10類。故采用一對多的分類方法。我們將多個(gè)類中的一個(gè)類標(biāo)記為正向類(y=1),然后將其他所有類都標(biāo)記為負(fù)向類,這個(gè)模型記作 。接著,類似的我們選擇另一個(gè)類標(biāo)記為正向類(y=2),再將其他類都標(biāo)記為負(fù)向類,將這個(gè)模型記為 ,依此類推。最后我們得到十條不同的分界函數(shù)。 在測試過程中,我們將測試樣本的X分別帶入這十個(gè)分界函數(shù) 中得到Z1,Z2,Z3…Z10。若ZK>0,而其他Z都不大于0,則測試樣本屬于第k類。若有多個(gè)Z值都大于0則取最大的。 2.2 matlab算法實(shí)現(xiàn) 2.2.1數(shù)據(jù)處理
clear; clc;
%% 讀取數(shù)據(jù) load ex3data1.mat; for i = 1:10 % 每個(gè)數(shù)字讀取前400個(gè)樣本 X_train([400*i-399:400*i],:) = X([500*i-499:500*i-100],:); y_train([400*i-399:400*i],:) = y([500*i-499:500*i-100],:); end m = size(X_train,1); class_y = zeros(m,10); X_train = [ones(m,1),X_train]; %將X擴(kuò)展 n = size(X_train,2); initial_theta = zeros(n,1); |
|
2.2.2調(diào)用matlab中的優(yōu)化工具箱 在邏輯回歸中代價(jià)函數(shù)為: 在設(shè)計(jì)代價(jià)函數(shù)的時(shí)候,為了避免出現(xiàn)過擬合的情況,我們往往加入了正則化,新的代價(jià)函數(shù)如下: 這樣在最小化代價(jià) 時(shí),會(huì)讓 的二次項(xiàng)盡可能小,從而避免的過擬合的情況。 要求代價(jià) 最小時(shí)的 值,于是我們調(diào)用優(yōu)化工具箱fminunc: %% 調(diào)用優(yōu)化工具箱 options = optimset('GradObj', 'on', 'MaxIter', 400); lamda = 0.1; for i = 1:10; class_y(find(y_train==i),i) = 1; [theta(:,i),cost(i)] = fminunc(@(t)(costfun(t,X_train,class_y(:,i),lamda)),initial_theta,options); end |
|
其中costfun函數(shù)如下所示: function [J,grad] = costfun(theta,X,y,lamda) m = size(X,1); Z = X*theta; H = sigmoid(Z); J = -1*sum(y.*log(H)+(1-y).*log(1-H))/m+lamda/(2*m)*sum(theta(2:end).^2); thetaj = theta; thetaj(1) = 0; grad = (X'*(H-y)+lamda*thetaj)/m; end |
|
2.2.3 測試 讀取上一步保存的訓(xùn)練參數(shù)thetazhenze。取一個(gè)測試樣本,帶入到 判斷Z的大小。 load thetazhenze; load ex3data1.mat; m = size(X,1); X = [ones(m,1),X]; i = 9;n = 50; %n作為偏移量在1:100中取,i作為數(shù)字類在0:9中取 H = X(500*(i+1)-100+n,:)*theta; [h,ind] =max(H); %取H中最大的標(biāo)簽 if ind == 10, ind = 0; end fprintf('the number is %d\n',ind) %輸出結(jié)果 |
|
2.2.4 輸出結(jié)果 ① 若未加入正則化,當(dāng)i等于9時(shí)輸出為8,發(fā)生錯(cuò)誤: ② 若加入正則化,當(dāng)i等于9時(shí)輸出為9,正確: 2.3 小結(jié) 一對多的邏輯回歸算法相比KNN算法增加了對訓(xùn)練集的訓(xùn)練過程,算法過程雖比KNN算法更復(fù)雜,但實(shí)際測試效果更理想。
第3章 總結(jié) 手寫數(shù)字識(shí)別的方法還有許多,例如可以用神經(jīng)網(wǎng)絡(luò)進(jìn)行識(shí)別。但時(shí)間有限,目前只用了這兩種方法,并用代碼實(shí)現(xiàn),識(shí)別的準(zhǔn)確率還有待提高。
完整的Word格式文檔51黑下載地址:
自研1703班滕翔模式識(shí)別.docx
(142.52 KB, 下載次數(shù): 15)
2017-12-19 16:18 上傳
點(diǎn)擊文件名下載附件
模式識(shí)別 下載積分: 黑幣 -5
|