Kaggle学习之路(二) —— Digit Recognizer之问题分析

来源:互联网 发布:mcgs组态软件实例教程 编辑:程序博客网 时间:2024/06/05 09:12
Digit Recognizer是数字手写体识别。Kirill Kliavin基于TensorFlow 框架与深度学习算法,给出了准确率高达0.99的解决方法,值得我们学习。

  • 阅读本篇的先决条件:需要有一定python基础,一些线性代数的理论基础,尤其是对于矩阵的处理。(矩阵的乘法,转置等)
  • 如果你对机器学习的原理感兴趣,推荐你学习Andrew Ng(吴恩达)的coursera的课程:https://www.coursera.org/learn/machine-learning

本篇主要说明Digit Recognizer的分析,代码我已经写了详细的注释,如果你感兴趣,请移步:https://github.com/Skyamz/Data_Recognizer

1. 明确我们的目标

让机器判断人类的手写体数字是几,并且输出出来。

2. 熟悉kaggle给的数据集

  • train.csv是训练集,这些数据用来建立一个模型。数字以图片的形式存储在电脑中,我们将这个数字图片分成784个像素(pixel),存储在一个向量里面。训练集的一行就表示一个向量,也就是一个数字。784列对应的就是784个像素。第一行label表明这一行是数字几。我们的数据有42000行,即有42000个手写的数字图片。第十行的数字‘8‘长这个样子:
    这里写图片描述


    这里写图片描述

        这个矩阵原理类似于我们去检查眼睛的时候,医生看我们是不是色盲时,用的那张卡片。这中间的每一个数字对应图片上的一个小块。

  • test.csv是测试集,这些数据用来检测我们的模型。我们的模型最后就是要输出测试集中的这28000张图片都是数字几。然后输出一个文件保存结果,输出文件长这样子:
    这里写图片描述

3. 数据的处理

    由于我们使用的kaggle数据集都是比较干净的,都是已经存储到784列里的(有784个像素),所以不用进行图片的放大缩小等处理。

3.1 减少图像的存储。

    经过统计,最大的pixel为255,要用2^7空间来存储。一共42000*784个像素,占的空间会很多,而且处理的时间会很慢。所以我们给images矩阵都乘以1.0/255.0来进行处理,把像素值控制在0-1之间。像素值越接近于1,就越黑,越接近于0越白。

images = np.multiply(images, 1.0 / 255.0)

    图像像素在0-255之间为灰度图像,我们训练集中的图像已经是灰度图像了。我们之所以不映射二值图像图像,而是除以1.0/255.0,是因为转化成二值图像信息损失太大,只有0,1两个数字,会造成判断的错误。

3.2 对train.csv第一列的label进行one-hot编码

  • one-hot编码是什么?

        我们现在有0-9这十个数字,我们创建十个一维矩阵。每个矩阵表示一个数字。如下所示:

    0 => [1 0 0 0 0 0 0 0 0 0]
    1 => [0 1 0 0 0 0 0 0 0 0]
    2 => [0 0 1 0 0 0 0 0 0 0]
    3 => [0 0 0 1 0 0 0 0 0 0]
    4 => [0 0 0 0 1 0 0 0 0 0]

    9 => [0 0 0 0 0 0 0 0 0 1]

    实现的代码如下

    def dense_to_one_hot(labels_dense, num_classes):    num_labels = labels_dense.shape[0]    index_offset = np.arange(num_labels) * num_classes    labels_one_hot = np.zeros((num_labels, num_classes))    labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1    return labels_one_hotlabels = dense_to_one_hot(labels_flat, labels_count)

    再来举一个更直观的例子:现在有一个订单,有三个feature:

    date=[“20170720”, “20170721”]fee=[“1000-2000”, “2000-3000”, “3000-4000”]person=[“Zhao”, “Qian”, “Sun”, “Li”]

    那么我们对上面三个feature的编码为:

    date=[01,10]fee=[001,010,100]person=[0001,0010,0100,1000]

        可以看出,编码位数取决于一个feature的种类数。哪一位生效,哪一位就对应为1。如果一个订单为[“20170721”, “2000-3000”, “Qian”]的话,它的one-hot编码就为[00,10 000,010,000 0000,0010,0000,0000],可以简写为[0,1 0,1,0 0,1,0,0]


  • 为什么要用one-hot编码?

    one-hot编码可以使类别独立出来,能够很好地处理离散型数据。我们这里要用到one-hot编码是因为后面要建立一个softmax层来给类别分配概率,这些概率是独立同分布的。所以要求输入的标签也应该是独立的,因此我们要对标签(0-9)进行one-hot编码。进而计算交叉熵。


3.3 划分训练集和验证集

    我们将train.csv再划分为两部分,一部分用来构建模型,另一部分来验证模型的准确率。我们这里取的验证validation_images是images的前VALIDATION_SIZE行,即取VALIDATION_SIZE个图片。取的训练集为images的VALIDATION_SIZE后面的所有行,即42000-VALIDATION_SIZE个图片。此处我们的VALIDATION_SIZE设置为2000。取了整个train.csv的5%的大小,是后期调参调出来的,开始一般取10%-25%,慢慢降低比例。

    validation_images = images[:VALIDATION_SIZE]    validation_labels = labels[:VALIDATION_SIZE]    train_images = images[VALIDATION_SIZE:]    train_labels = labels[VALIDATION_SIZE:
                                     memoryjdch编辑于2017.7.14
原创粉丝点击