機器學(xué)習(xí)識別手寫數(shù)字圖像

手寫數(shù)字圖像識別作為機器學(xué)習(xí)入門教程。本文分別使用KNN、SVM算法實現(xiàn)手寫數(shù)字識別后續(xù)教程繼續(xù)補充全連接神經(jīng)網(wǎng)絡(luò)和卷積神經(jīng)網(wǎng)絡(luò)的識別,對比不同算法的實現(xiàn)難度、訓(xùn)練耗時、準(zhǔn)確率等參數(shù)。

歡迎關(guān)注個人博客

數(shù)據(jù)

使用Google的手寫數(shù)字圖像,數(shù)據(jù)中包含55000的訓(xùn)練數(shù)據(jù),10000的測試數(shù)據(jù)和5000條驗證數(shù)據(jù),下載地址

標(biāo)記數(shù)據(jù)包含0-9一共10個數(shù)字,是一個多分類問題,詳細(xì)介紹可以參看MNIST 入門 。

KNN算法

最近最鄰算法,這是一種有監(jiān)督算法,思路非常簡單,簡單說就是“物以類聚”,通過對標(biāo)記數(shù)據(jù)進行訓(xùn)練以后,對于預(yù)測數(shù)據(jù),由最近K的鄰居投票,決定這個數(shù)據(jù)屬于哪個類,非常適合多分類問題,通常情況下準(zhǔn)確度非常好。這里使用sklearn包給出的knn接口

knn = KNeighborsClassifier(n_neighbors=10, n_jobs=8, leaf_size=10)

__init__(self, n_neighbors=5,
         weights='uniform', algorithm='auto', leaf_size=30,
         p=2, metric='minkowski', metric_params=None, n_jobs=1,
         **kwargs):

附近10個neighbors,啟動8個線程訓(xùn)練,葉子大小控制為10,距離使用默認(rèn)的歐氏距離。訓(xùn)練數(shù)據(jù)只選用10000個樣本,準(zhǔn)確率達到0.9146,訓(xùn)練耗時0.546s

SVM算法

作為經(jīng)典機器學(xué)習(xí)算法,支持向量機具有很大的價值,其應(yīng)用面非常廣,可以適用于線性和非線性分類。但默認(rèn)是線性分類,需要選擇非線性核,非線性核將原來線性不可分的樣本,映射到更高維空間,變得線性可分。如何映射成線性可分,有一定難度,暫時不詳說。

支持向量機是一種二分類算法,通過構(gòu)建多種分類器,來支持多分類問題,常用的有ovoovr,本文依然使用sklearn包給出的接口。

svc = SVC(C=10)

def __init__(self, C=1.0, kernel='rbf', degree=3, gamma='auto',
             coef0=0.0, shrinking=True, probability=False,
             tol=1e-3, cache_size=200, class_weight=None,
             verbose=False, max_iter=-1, decision_function_shape='ovr',
             random_state=None):

其余參數(shù)使用默認(rèn)值,默認(rèn)非線性核rbf, 多分類采用ovr。訓(xùn)練數(shù)據(jù)只選用10000個樣本,準(zhǔn)確率達到0.9206,訓(xùn)練耗時19.226s

代碼分析

所有代碼可以移步github下載,這里主要介紹模型訓(xùn)練的接口

import os.path
from sklearn.externals import joblib
import logging
import time
from data import validation

logger = logging.getLogger(__file__)


def add_model(model_name, model=None):
    """
    加載模型,如果存在直接返回,否則重新訓(xùn)練模型
    :param model_name: 模型名稱
    :param model: sk-learn 創(chuàng)建的模型對象
    :return: model
    """
    if os.path.exists(model_name):
        logger.info("%s is exist, load ...", model_name)
        return joblib.load(model_name)

    if model is None:
        logger.error("please set model")
        return

    from data import train, test
    logger.info("start train model")
    tic = time.time()
    model.fit(train.images[:10000], train.labels[:10000])  # 10000 train
    logger.info("%s cost %s to train model", model_name, time.time() - tic)

    score = model.score(test.images[:5000], test.labels[:5000])  # 5000 test
    logger.info("%s score is %s", model_name, score)
    joblib.dump(model, model_name)
    logger.info("save model as %s", model_name)
    return model


def validation_model(model):
    """輸出模型的驗證數(shù)據(jù)"""
    data, targets = validation.images[:10], validation.labels[:10]  # 10 validation
    predicts = model.predict(data)
    for y_, y in zip(predicts, targets):
        logger.info("預(yù)測值: %s 真實值:%s", y_, y)

add_model接口如果模型存在,則直接返回模型對象,如果不存在,則需要重新訓(xùn)練模型并保存。

主程序支持加載多個模型,但只能單線程的依次訓(xùn)練,有興趣可以改成多進程訓(xùn)練,最大程度的使用CPU。多個模型加載需要使用model模塊中的Model類啟動訓(xùn)練。

from api import add_model, validation_model


class Model:
    def __init__(self):
        self._model_name = []
        self._model = []

    def add(self, model_name, model):
        self._model_name.append(model_name)
        self._model.append(model)

    @staticmethod
    def _run_model(model_name, model):
        model = add_model(model_name, model)
        validation_model(model=model)

    def run(self):
        for _ in map(self._run_model, self._model_name, self._model):
            pass

主函數(shù)中只需要定義好模型,然后通過model對象的add()方法添加,然后啟動run()方法,就可以依次訓(xùn)練模型。

from config import LOG_CONF
import logging
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from model import Model

logging.basicConfig(**LOG_CONF)
logger = logging.getLogger(__file__)

if __name__ == '__main__':
    models = Model()
    svc = SVC(C=10)
    models.add(model_name='svc.model', model=svc) # 添加模型
    knn = KNeighborsClassifier(n_neighbors=10, n_jobs=8, leaf_size=10)
    models.add(model_name='knn.model', model=knn) # 添加模型
    models.run() # 啟動

代碼在這里

參考文檔

MNIST 入門

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容