机器学习 — 再认识数据集

  做了一些简单机器学习任务后,发现必须要对数据集有足够的了解才能动手做一些事,这是无法避免的,否则可能连在干嘛都不知道,而一些官方例程并不会对数据集做过多解释,你甚至连它长什么样都不知道。。。

  以sklearn的手写数字识别为例,例子中,一句

digits = datasets.load_digits()

  就拿到数据了,然后又几句

images_and_labels = list(zip(digits.images, digits.target))
for index, (image, label) in enumerate(images_and_labels[:4]):
    plt.subplot(2, 4, index + 1)
    plt.axis('off')
    plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
    plt.title('Training: %i' % label)

# To apply a classifier on this data, we need to flatten the image, to
# turn the data in a (samples, feature) matrix:
n_samples = len(digits.images)
data = digits.images.reshape((n_samples, -1))

  就把数据集划分好了,对初学者来说,可能都不知道干了些啥。。。当然更重要的是,跑一边程序看到效果不错,想要用训练好的模型玩玩自己的数据集,却无从下手。。。于是,下面就以这个例子来说一下,如何基本的了解数据集,以及如何构造数据集,或许还会谈谈为什么要这样构造。。。

  1.认识数据集。

  看代码,我们发现,该数据集主要由两个部分组成:

    1).images

    2).target

  target 的划分看起来不复杂,所以可以直接看看其中的部分内容:

>>> print(digits.images.shape)
# (1797,)
>>> print(digits.target[:10])
# [0 1 2 3 4 5 6 7 8 9]
>>> print(digits.target[-10:])
# [5 4 8 8 4 9 0 8 9 8]

  含义是:target是一个形状为长度为1797的行向量,共有1797个(0~9)数字。

  images 还需要做一些处理才能使用fit接口,但我们也先看看原本长什么样:

>>> print(digits.image.shape)
# (1797, 8, 8)
>>> print(digits.images[0].shape)
# (8, 8)
>>> print(digits.images[0])
'''
[[ 0.  0.  5. 13.  9.  1.  0.  0.]
 [ 0.  0. 13. 15. 10. 15.  5.  0.]
 [ 0.  3. 15.  2.  0. 11.  8.  0.]
 [ 0.  4. 12.  0.  0.  8.  8.  0.]
 [ 0.  5.  8.  0.  0.  9.  8.  0.]
 [ 0.  4. 11.  0.  1. 12.  7.  0.]
 [ 0.  2. 14.  5. 10. 12.  0.  0.]
 [ 0.  0.  6. 13. 10.  0.  0.  0.]]
'''

  再画出来看看:

>>> import matplotlib.pyplot as plt
>>> plt.axis('off')
>>> plt.title('label: %i' % digits.target[0])
>>> plt.imshow(digits.images[0], cmap='gray_r')
>>> plt.show()

  

  含义是:images是由1797张尺寸为8*8的单通道图片组成,而图片内容对应每一张标签的数字的手写数字。

  于是,这下我们了解了数据集了,但别急,图片集还要做点处理才能使用:

>>> data = digits.images.reshape((n_samples, -1))
>>> print(data.shape)
# (1797, 64)
>>> print(data[0])
'''
[ 0.  0.  5. 13.  9.  1.  0.  0.  0.  0. 13. 15. 10. 15.  5.  0.  0.  3.
 15.  2.  0. 11.  8.  0.  0.  4. 12.  0.  0.  8.  8.  0.  0.  5.  8.  0.
  0.  9.  8.  0.  0.  4. 11.  0.  1. 12.  7.  0.  0.  2. 14.  5. 10. 12.
  0.  0.  0.  0.  6. 13. 10.  0.  0.  0.]
'''

  把原图片集形状 (numbers, w, h) 变成了 (numbers, w * h),也就是把2维数组变为一维数组来存储,我个人认为是为了效率...处理一维数组的效率比二维数组高很多。(使用深度学习,我们可以利用神经网络自己构造输入形状和输出形状,便利许多。)

  现在我们很清楚模型要输入什么样的数据才能进行训练了。

  2.训练模型。

  该例子使用svm,不同问题的选择不一,而是根据对算法的理解、经验和观察最终训练效果选择合适的算法。

from sklearn import datasets, svm


digits = datasets.load_digits()
n_samples = len(digits.images)
train_x = digits.images.reshape((n_samples, -1))
train_y = digits.target

model = svm.SVC(gamma=0.001)
model.fit(train_x, train_y,)

  3.评估模型的效果。

from sklearn import metrics

y_real = dateset.target
...
y_pred = model.predict(test_x)
print(metrics.accuracy_score(y_real, y_pred))

  4.保存和加载模型。

  保存模型很简单,sklearn有专门提供便利的方法来保存和加载模型:

from sklearn.externals import joblib

joblib.dump(model, 'mnist.m')

  加载模型:

model = joblib.load('mnist.m')
y_pred = model.predict(test_x)

  5.最后,部署模型。

  上面看到,图片的形状必须为8*8像素大小的单通道图片,假如我们有一批50*50的手写数字图片集,想用该模型测试一下效果怎么办,我们只需要改变一下图片分辨率,把形状变为8*8即可。这样,我们才能用自己的数据集来进行测试,或者部署该模型以提供给别人使用。

  关于如何部署到web,可以参考前一篇随笔

  下面是一个例子,使用了一点opencv来把RGB图片转为灰度图、修改图片尺寸以及一些简单的额外处理:

from sklearn import datasets, svm, metrics
import matplotlib.pyplot as plt
from sklearn.externals import joblib
import numpy as np
import cv2 as cv


digits = datasets.load_digits()
n_samples = len(digits.images)
train_x = digits.images.reshape((n_samples, -1))
train_y = digits.target

model = svm.SVC(gamma=0.001)
model.fit(train_x, train_y,)
joblib.dump(model, 'mnist.m')

w, h = 8, 8
labels = [0, 1, 4, 5]
lenght = len(labels)
images = np.zeros((lenght, h, w), np.uint8)
imgs = []
for i, name in enumerate(labels):
    img = cv.imread('digits/{}.png'.format(name), cv.IMREAD_GRAYSCALE)
    img = cv.resize(img, (h, w), interpolation=cv.INTER_CUBIC)
    for r in range(img.shape[0]):
        for c in range(img.shape[1]):
            if np.all(img[r, c] <= [251, 251, 251]):
                img[r, c] = (0, 0, 0)
    imgs.append(img)
    # gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # lap = cv.Laplacian(gray, cv.CV_64F)
    images[i] = img
images = images.reshape((lenght, -1))
# model = joblib.load('mnist.m')
pred = model.predict(images)
print(metrics.accuracy_score(labels, pred))
for index, (image, label) in enumerate(list(zip(imgs, pred))):
    plt.subplot(1, lenght, index + 1)
    plt.axis('off')
    plt.imshow(image, cmap='gray_r', interpolation='nearest')
    plt.title('pred: %i' % label)
plt.show()

  嘛,虽然最后结果很糟。。4张图片识别率只有25%,唯一一张识别成功的,还是因为,数据全部被识别为1,也不知道为啥。。。

  自己断断续续玩了也有一段时间了,能懂如何生成数据,如何构造模型,如何部署模型等,嘛,很糟糕的说,也算有点成长吧。。。

猜你喜欢

转载自www.cnblogs.com/darkchii/p/10048035.html