數字手寫識別——Java實現KNN算法


引言

手寫識別也是當前機器學習的一大熱點,數字手寫識別是手寫識別中的基礎,我們用到的是knn算法,今天給大家講一下我的實現方法;


環境

IDE:Eclipse
語言:Java


項目:數字手寫識別

思路

數據采集:我們知道,一張圖片可以被看作一個個點組成的矩陣,對於手寫數字,我們只要創建一個全0數組當作背景,手寫完畢把數字所占區域置為1,就可以保存當作一個樣本了,如下圖所示。
這里寫圖片描述
算法:KNN算法,其距離度量我們采用歐拉距離。
歐拉距離計算方法:我們將數組看作40*40向量,采用距離公式計算。

這里寫圖片描述

實現

一、面板

請原諒作者對於美笨拙的感知,我所繪制的界面不能夠再簡單了。如圖:

面板按鈕介紹

  • Identify:識別手寫的數字;
  • Save this example: 保存這個樣例到數據集;
  • 數字下拉框:相當於保存數據集的標簽,例如,要保存手寫“2”,先下拉選好2再保存即可

這里寫圖片描述

二、存儲

在數據讀取存儲上走了很多彎路,之后要好好總結下數據流的幾個傳輸方式。
我們將每張圖片轉化為一個二維數組后,存放進一個txt文件中。對於每個單獨的文件,我們要產生一個獨一無二的文件名,所以文件取名方式采取“數字+隨機id .txt”的格式命名,隨機id我們通過構造UID對象,獲取其hashcode值作為id。

            //獲取下拉框選中的數字
            String selectedNumber=cbItem.getSelectedItem().toString();
            UID id=new UID();
            //文件的前綴路徑
            String rootPath="C:\\Users\\DearYou\\eclipse-workspace\\GUI\\src\\Demo\\handwritingIdentify\\TrainingData\\";
            //生成文件名
            String fileName=selectedNumber+"-"+id.hashCode();
            //生成絕對路徑下的一個文件
            String absoluteFile=rootPath+fileName+".txt";
            File file=new File(absoluteFile);
            try {
                //創建文件
                if(!file.exists())
                    file.createNewFile();
                //將數組寫入文件
                FileWriter out = new FileWriter(file);
                for(int i=0;i<40;i++) {
                    for(int j=0;j<40;j++) {
                        out.write(pixel[i][j]+"");
                    }
                }
                out.flush();
                out.close();
            }catch(Exception e1) {
                e1.printStackTrace();
            }

三、Knn算法實現

Common thinking :KNN目的是找到k個離測試樣本最近的訓練樣本,看了下同學的方法,大多都使用了排序,但自己想想排序實在是多余,一個排序就將復雜度升到了O(nlgn),數據容量一大,性能就會下降。
My thinking:我想我們只要找到k個距離最近的樣本,和順序並沒有關系。筆者細想了一下,我么只要構建一個大小為k的數組或者隊列,對於前k個元素,我們直接放進數組,后面的n-k個元素,我們找到存放在數組中的k個元素中最大值,將二者比較看是否替代。這樣我們只需遍歷一遍,復雜度降為O(n),也是一種小優化。

    偽代碼:
    KnnNode[] dist=new KnnNode[k];
    for(int i=0->k){
        KnnNode temp=new KnnNode(distance);
        dist.append(temp)
    }
    for(the rest of test set){
        if(temp.distance < the maximum element in dist)
            dist[index of max]=temp;
    }

四、預測

方法如下展示:
這里寫圖片描述
我們也可以在識別之后保存該樣本,這樣不能不斷擴大數據集,讓精度更高。


總結

雖然能在O(n)復雜度里實現Knn算法,但是我的knn延展性太差,我應該可以把這個knn的參數換成算好的距離,而不是傳入的數組,這樣就能將這個KNN封裝好方便以后再用。
源代碼參考地址:https://github.com/Gray-way/HandwritingRecognition


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM