SkLearn之MLP

Multi-layer Perceptron即多层感知器,也就是神经网络,要说它的Hello world,莫过于识别手写数字了。如果你已经了解它的原理并尝试过自己写一个后就可以试用下通用的类库,好将来用在生产环境。下面是使用SkLearn中的MLPClassifier识别手写数字,代码是在Python2.7上运行。
首先获取数据集,我是在http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz下载的,也可以直接搜索mnist.pkl.gz来获取。数据集大小可能有区别,但数组中的每一行都表示一个灰度图像。每个元素都表示像素所对应的灰度值。
先来初步查看下数据


from sklearn.neural_network import MLPClassifier
import numpy as np
import pickle
import gzip
import matplotlib.pyplot as plt

# 加载数据
with gzip.open(r"mnist.pkl.gz") as fp:
    training_data, valid_data, test_data = pickle.load(fp)

X_training_data, y_training_data = training_data
X_valid_data, y_valid_data = valid_data
X_test_data, y_test_data = test_data

def show_data_struct():
    print X_training_data.shape, y_training_data.shape
    print X_valid_data.shape, y_valid_data.shape
    print X_test_data.shape, y_test_data.shape
    print X_training_data[0]
    print y_training_data[0]

show_data_struct()

重点注意数据已经归一化,就是把数值映射到0到1之间,这对于mlp是很有必要的。

为什么要把数据分为训练集,测试集?

另外这里把数据分为了三类,分别为训练集,验证集,测试集。大多数时候是分为训练集和测试集。当然如果我们直接收集到的数据没有分开,训练模型时要自己分为训练集和测试集。
将原始数据分开,保证用于测试的数据是训练模型时从未遇到的数据可以使测试更客观。否则就像学习教课书的知识,又只考教课书的知识,就算不理解记下了就能得高分但遇到新问题就傻眼了。
好一点的做法就是用训练集当课本给他上课,先找出把课本知识掌握好的人,再参加由新题组成的月考即测试集,若是还是得分高,那就是真懂不是死记硬背了。
但这样选出来的模型实际是还是用训练集和测试集共同得到的,再进一步,用训练集和验证集反复训练和检测,得到最好的模型,再用测试集来一局定输赢即期末考试,这样选出来的就更好了。
这里就不搞这么复杂了,将training,validation合并,把数据分为训练集和测试集。
接下来先看下这些手写数字长什么样。


from sklearn.neural_network import MLPClassifier
import numpy as np
import pickle
import gzip
import matplotlib.pyplot as plt

# 加载数据
with gzip.open(r"mnist.pkl.gz") as fp:
    training_data, valid_data, test_data = pickle.load(fp)

X_training_data, y_training_data = training_data
X_valid_data, y_valid_data = valid_data
X_test_data, y_test_data = test_data

# 合并训练集,验证集
X_training = np.vstack((X_training_data, X_valid_data))
y_training = np.append(y_training_data, y_valid_data)

def show_image():
    plt.figure(1)
    for i in range(10):
        image = X_training[i]
        pixels = image.reshape((28, 28))
        plt.subplot(5,2,i+1)
        plt.imshow(pixels, cmap='gray')
        plt.title(y_training[i])
        plt.axis('off')
    plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.45,
                        wspace=0.85)
    plt.show()

show_image()
Figure_1.png

这是测试集中的前10个数字,一眼就可以看出写的是什么。注意在上面的代码有一行是把图片对应的一行数据转为28 *28的二维数组,这个不转不行啊!把任何一个图片每行首尾相连,看一个1个像素高768个像素宽的图片,那可没办法知道写的是什么。那么问题来了,我们人看到的是一个二维的图片,而给模型输入的是个一维数组,丢失了原始图片的长宽比例信息,这样它还能识别出来吗?
呃呃呃,哦----,哦-----。当我说这些时你知道我想表示不知道,对不对?我们约定好一分钟内前30秒滴滴滴后30秒哒哒哒表示1,前20秒哒哒哒后40秒滴滴滴表示2,这样用一连串声音信号就能表示数字信息了。同样将图片从上到下从左到右逐个像素填到一个长度为768的向量,变成一个像素高度的图片,从左到右看过去就是一会儿白一会儿黑,就像刚才说的声音一样,它也能表示不同的数字。所以模型识别的并不是原始的图片而是转换后的一个向量。
现在就来看看效果

from sklearn.neural_network import MLPClassifier
import numpy as np
import pickle
import gzip
import matplotlib.pyplot as plt

# 加载数据
with gzip.open(r"mnist.pkl.gz") as fp:
    training_data, valid_data, test_data = pickle.load(fp)

X_training_data, y_training_data = training_data
X_valid_data, y_valid_data = valid_data
X_test_data, y_test_data = test_data
# 合并训练集,验证集
X_training = np.vstack((X_training_data, X_valid_data))
y_training = np.append(y_training_data, y_valid_data)

def train():
    mlp = MLPClassifier()
    # 查看默认超参
    print mlp
    # 训练模型
    mlp.fit(X_training, y_training)
    print(mlp.score(X_test_data, y_test_data))


train()

我测试的分数是0.9807,还不低是不是?现在全用默认参数,如果再优化下,还能不能再提高些呢?下面用gridSearchCV来试下。

from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import GridSearchCV
import numpy as np
import pickle
import gzip
import matplotlib.pyplot as plt

if __name__ == '__main__':
    # 加载数据
    with gzip.open(r"mnist.pkl.gz") as fp:
        training_data, valid_data, test_data = pickle.load(fp)

    X_training_data, y_training_data = training_data
    X_valid_data, y_valid_data = valid_data
    X_test_data, y_test_data = test_data
    # 合并训练集,验证集
    X_training = np.vstack((X_training_data, X_valid_data))
    y_training = np.append(y_training_data, y_valid_data)
    mlp_clf__tuned_parameters = {"hidden_layer_sizes": [(100,), (100, 30)],
                                 "solver": ['adam', 'sgd', 'lbfgs'],
                                 "max_iter": [20],
                                 "verbose": [True]
                                 }
    mlp = MLPClassifier()
    estimator = GridSearchCV(mlp, mlp_clf__tuned_parameters, n_jobs=6)
    estimator.fit(X_training, y_training)

    print estimator.get_params().keys()
    print estimator.best_params_

这里的max_iter是想让它快些结束才设置为20默认是200,这样得到的最优参数自然不是真正的最优参数。这里虽然只调两个参数,排列组合得到的6种情况并行计算,还是很卡很慢。实际调参要先明白各参数的含义,预先猜测最好的值去测试,还要借助其它方法才能快速有效的调参。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341