Kaggle练习赛之数字识别——新手适用

项目介绍

该项目通过算法识别图像的数字,图像由783个像素特征即灰度值组成,范围一般从0到255,白色为255,黑色为0,选择算法依据据783个特征判断图像是哪一个数字(标签),因为练习赛,难度还是比较低的。https://www.kaggle.com/c/digit-recognizer

提供数据集(在链接的data中可下载)有,train.csv(包含1列label 和783列pixelx,数据大小为42001*785)、test.csv(含7834列pixelx,数据大小为28001*784)

 

算法原理

此处选择的算法是python的sklearn库中的K近邻算法,当然大家也可以尝试用其他算法,比如朴素贝叶斯、支持向量SVC等,最后K近邻算法的准确率最高所以选择此

K近邻算法KNN原理是:根据与待测试样本距离最近的k个训练样本的大概率分类来判断待测样本所归属的类别

过程是:

1)计算测试数据与各个训练数据之间的距离;

2)按照距离的递增关系进行排序;

3)选取距离最小的K个点;

4)确定前K个点所在类别的出现频率;

5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

 

实现代码

1. 预处理

读取训练数据集,拆分为trainlabel 和traindata两个矩阵,同时数值化和归一化

 train = pd.read_csv("train.csv")
    trainlabel = ravel(toint(train.iloc[:, 0]).transpose())
    traindata = toint(train.iloc[:, 1:])

    test = pd.read_csv("test.csv")
    testdata = toint(test.values)

    # 对traindata和testdata归一化,将所有不为0的数值全部转换为1
    train_rows = traindata.shape[0]
    train_columns = traindata.shape[1]
    test_rows = testdata.shape[0]
    test_columns = testdata.shape[1]

    traindata = nomalizing(traindata, train_rows, train_columns)
    testdata = nomalizing(testdata, test_rows, test_columns)

此处解释一下以上提到的两个预处理方法:

①数值化是指原数据集的数据类型可能是字符串,由于后面会做是否为0的判断,所以需要将数据类型转换为数值型,由toint()函数完成

def toint(array):
    """转为数值型数据"""
    array = mat(array)# 生成矩阵
    m, n = shape(array)
    newArray = zeros((m, n))
    for i in range(m):
        for j in range(n):
            newArray[i, j] = int(array[i, j])
    return newArray

②归一化是指将所有不为0的数都转变为1,目的是简化操作,由nomalizing函数实现

def nomalizing(data,r,l):
    """一个标签对应784个特征,特征值为0-255的灰度值,0代表黑色,255代表白色,此处将所有不为0的值都以1转换,简化工作量"""
    for i in range(r):
        for j in range(l):
            if data[i,j] != 0:
                data[i,j] = 1
    return data

2. 交叉检验

使用交叉检验,目的是评估n_neighbors参数的最佳取值,减少过拟合。
因为此处只控制一个参数k,即n_neighbors参数,所以用模型选择库中的cross_val_score(),若有多个参数则需使用GridSearchCV()

scores_list = []
k_range = range(1,10)
for k in k_range:
    knnclf = KNeighborsClassifier(k)
    scores = cross_val_score(knnclf,traindata,trainlabel,cv=10,scoring="accuracy")
    scores_list.append(mean(scores))
plt.plot(k_range,scores_list)
plt.show()
print(max(scores_list))    # 最大精准度
k = argsort(array(scores_list))[-1]    # 最大精准度对应的k值

此处将k值得范围锁定到1-9,cv=10设定为十折交叉验证,score ="accuracy"评分标准采用精确率,默认是以 scoring=’f1_macro’

取得k值和对应准确率的折线图,可得到最佳k值和最大准确率

3. 算法实现

def knnClassify(k,data,label,test):
    """KNN算法"""
    knnclf = KNeighborsClassifier(k)
    knnclf.fit(data,ravel(label))    # label降维一维数据
    testlabel = knnclf.predict(test)
    save_result(testlabel,"testlabel.csv")


def save_result(data,filename):
    """保存预测结果"""
    # newline参数是控制文本模式之下,一行的结束字符
    with open(filename,'w',newline="") as f:
        w = csv.writer(f)
        for d in data:
            tmp = []
            tmp.append(d)
            w.writerow(tmp)

lavel()的作用是将多维数组降为一维,由于label只有一列数值,每一行特征对应一个label,需要将shape转变为(42000,)的形式,所以必须降维

扩展:lavel()和flatten()有一样的效果,不过唯一区别是flatten返回的是副本,而如果改变lavel会改变原数据

最后得到预测的标签testlabel.csv文件。

 

这个项目还有很多解法,这边介绍的较基础,如果有余力和兴趣可以去https://blog.csdn.net/weixin_39655021/article/details/86763519看看更高深的解法

本文参考了https://blog.csdn.net/hermito/article/details/51862733内容

敬礼

你可能感兴趣的:(kaggle,KNN)