打造人工智障初步

最近做了一个sofasofa社区上的一个给ML新手入门用的数据竞赛:识别一张带噪声的图片中画的是圆形还是方形。

训练集中共有\(4000\)个灰度图像,预测集中有\(3550\)个灰度图像。每个图像中都会含有大量的噪点。 图像的分辨率为\(40\times40\),也就是\(40\times40\)的矩阵,每个矩阵以行向量的形式被存放在train.csvtest.csv中。train.csvtest.csv中每行数据代表一个图像,也就是说每行都有\(1600\)个特征。

变量名 解释
id 编号
p_i_j 表示图像中第\(i\)行第\(j\)列上的像素点的灰度值,取值范围在\(0\)\(255\)之间,\(i\)\(j\)的取值都是\(0\)\(39\)
y 表示该图像中的形状。\(0\)表示圆形,\(1\)表示方形。这是需要被预测的标签。

我们来看一下这些数据长什么样,先写一个函数把灰度数据转成图像:

以下分别是训练集中的一个矩形和一个圆形:

在这里,我们用一个简单的浅层CNN来训练。第一个卷积层有\(32\)filter,第二个卷积层有\(64\)filter,它们的尺寸都是\(5\times 5\)stride都是\(1\)

import tensorflow as tf
import pandas as pd
import numpy as np

def load_data(position, total):
    x = train_data[position: position + total].drop(["id", "y"], axis=1).values
    x.resize((total, 40, 40, 1))
    y = train_data[position: position + total][["y"]].values
    y.resize((total, ))
    y_onehot = np.zeros((total, 2))
    for i in range(total):
        y_onehot[i][y[i]] = 1
    return x, y_onehot

def train_accuracy_op():
    std = tf.argmax(input_y, axis=1)
    my = tf.argmax(fully_3, axis=1)
    return tf.reduce_mean(tf.cast(tf.equal(std, my), tf.float32))

input_x = tf.placeholder(tf.float32, shape=(None, 40, 40, 1))
input_y = tf.placeholder(tf.int32, shape=(None, 2))

conv_1 = tf.layers.conv2d(
    inputs=input_x,
    filters=32,
    kernel_size=[5, 5],
    strides=1,
    padding='same',
    activation=tf.nn.relu
)

pool_1 = tf.layers.max_pooling2d(
    inputs=conv_1,
    pool_size=[2, 2],
    strides=2
)

conv_2 = tf.layers.conv2d(
    inputs=pool_1,
    filters=64,
    kernel_size=[5, 5],
    strides=1,
    padding='same',
    activation=tf.nn.relu
)

pool_2 = tf.layers.max_pooling2d(
    inputs=conv_2,
    pool_size=[2, 2],
    strides=2
)

flatten_3 = tf.layers.flatten(
    inputs=pool_2
)
# shape of (None, 500)

fully_3 = tf.contrib.layers.fully_connected(
    inputs=flatten_3,
    num_outputs=2,
    activation_fn=None
)
# shape of (None, 2)

loss = tf.losses.softmax_cross_entropy(
    onehot_labels=input_y,
    logits=fully_3
)

train_op = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(loss=loss)
train_data = pd.read_csv("./data/train.csv")
batch_size = 100
test_x, test_y = load_data(3900, batch_size)

sess = tf.Session()
sess.run(tf.global_variables_initializer())
for epoch in range(100):
    for i in range(39):
        x, y = load_data(i * batch_size, batch_size)
        sess.run(train_op, feed_dict={
            input_x: x,
            input_y: y
        })
    current_loss, current_accuracy = sess.run([loss, train_accuracy_op()], feed_dict={
        input_x: test_x,
        input_y: test_y
    })
    print("This is epoch %d, current loss is %f, current accuracy is %f" % (epoch, current_loss, current_accuracy))

掏出一个tensorflow库,我们只要简单的做一些上层设计就ok了。

调试通之后结果非常漂亮。我把\(4000\)个训练集分成两部分,前\(3900\)分成train_set,后\(100\)分成test_set。在经过\(11\)epoch之后,模型在test_set上的精度就已经到了\(100\%\)(事实上我给测试集的数量应该偏少了)。

This is epoch 0, current loss is 0.513905, current accuracy is 0.900000
This is epoch 1, current loss is 0.227106, current accuracy is 0.940000
This is epoch 2, current loss is 0.139139, current accuracy is 0.970000
This is epoch 3, current loss is 0.102229, current accuracy is 0.970000
This is epoch 4, current loss is 0.079293, current accuracy is 0.980000
This is epoch 5, current loss is 0.062797, current accuracy is 0.980000
This is epoch 6, current loss is 0.050775, current accuracy is 0.980000
This is epoch 7, current loss is 0.042209, current accuracy is 0.980000
This is epoch 8, current loss is 0.036351, current accuracy is 0.980000
This is epoch 9, current loss is 0.031861, current accuracy is 0.980000
This is epoch 10, current loss is 0.028251, current accuracy is 0.990000
This is epoch 11, current loss is 0.025071, current accuracy is 1.000000
This is epoch 12, current loss is 0.022569, current accuracy is 1.000000
This is epoch 13, current loss is 0.020529, current accuracy is 1.000000
This is epoch 14, current loss is 0.018822, current accuracy is 1.000000
This is epoch 15, current loss is 0.017304, current accuracy is 1.000000
This is epoch 16, current loss is 0.015985, current accuracy is 1.000000
This is epoch 17, current loss is 0.014798, current accuracy is 1.000000
This is epoch 18, current loss is 0.013815, current accuracy is 1.000000
This is epoch 19, current loss is 0.012896, current accuracy is 1.000000
This is epoch 20, current loss is 0.012053, current accuracy is 1.000000
This is epoch 21, current loss is 0.011385, current accuracy is 1.000000
This is epoch 22, current loss is 0.010850, current accuracy is 1.000000
This is epoch 23, current loss is 0.010411, current accuracy is 1.000000
This is epoch 24, current loss is 0.009914, current accuracy is 1.000000
This is epoch 25, current loss is 0.009527, current accuracy is 1.000000
This is epoch 26, current loss is 0.009172, current accuracy is 1.000000
This is epoch 27, current loss is 0.008819, current accuracy is 1.000000
This is epoch 28, current loss is 0.008466, current accuracy is 1.000000
This is epoch 29, current loss is 0.008108, current accuracy is 1.000000
This is epoch 30, current loss is 0.007808, current accuracy is 1.000000
This is epoch 31, current loss is 0.007545, current accuracy is 1.000000
This is epoch 32, current loss is 0.007304, current accuracy is 1.000000
This is epoch 33, current loss is 0.007066, current accuracy is 1.000000
This is epoch 34, current loss is 0.006845, current accuracy is 1.000000
This is epoch 35, current loss is 0.006643, current accuracy is 1.000000
This is epoch 36, current loss is 0.006452, current accuracy is 1.000000
This is epoch 37, current loss is 0.006276, current accuracy is 1.000000
This is epoch 38, current loss is 0.006100, current accuracy is 1.000000
This is epoch 39, current loss is 0.005923, current accuracy is 1.000000
This is epoch 40, current loss is 0.005762, current accuracy is 1.000000
This is epoch 41, current loss is 0.005609, current accuracy is 1.000000
This is epoch 42, current loss is 0.005485, current accuracy is 1.000000

最后成功进了前\(10\),处女作,爽!