sw1227’s diary

Visualization, GIS, Machine Learning, Generative Art, Simulation, Math

MNIST互換の日本語くずし字データセットでCNNやt-SNEを試す

1. くずし字データセットとは

以前から公開されていた日本古典籍データセットでは、デジタル化されたくずし字の画像をダウンロードすることが可能でした。

人文学オープンデータ共同利用センターのニュース(2018/12/08)によると、この日本古典籍くずし字データセットを元に、MNISTデータセット互換のくずし字データセット「KMNIST」が公開されたそうです。詳細はGitHubや以下のリンクを参照していただければ良いのですが、おなじみのMNISTデータセットと同様、10クラスに分類できる28x28のグレースケール画像が70,000枚(訓練用60,000・テスト用10,000)提供されています。また、Kuzushiji-49という49クラスの拡張版データセットもあるようです。

codh.rois.ac.jp

この記事では、このKuzushiji-MNISTをダウンロードし、クラスごとの画像の可視化・t-SNEによる次元削減・ベンチマークのCNN(Keras)による識別までを実行してみます。

2. ダウンロード

手順はGitHubを参照します。直接ダウンロードすることも可能ですが、今回はレポジトリをgit cloneしてダウンロードスクリプトを実行することでダウンロードしてみました。

git clone https://github.com/rois-codh/kmnist.git
cd kmnist
python download_data.py

download_data.pyを実行すると以下のようにデータの種別・形式を選択するよう求められます。今回はKuzushiji-MNISTデータセット.npz形式でダウンロードしました。

Please select a download option:
1) Kuzushiji-MNIST (10 classes, 28x28, 70k examples)
2) Kuzushiji-49 (49 classes, 28x28, 270k examples)
3) Kuzushiji-Kanji (3832 classes, 64x64, 140k examples)
> 1
Please select a download option:
1) MNIST data format (ubyte.gz)
2) NumPy data format (.npz)
> 2
Downloading kmnist-train-imgs.npz - 17.0 MB
Downloading kmnist-train-labels.npz - 0.0 MB
Downloading kmnist-test-imgs.npz - 2.0 MB
Downloading kmnist-test-labels.npz - 0.0 MB
All dataset files downloaded!

3. データを眺める

前章でダウンロードした4つの.npzファイルを以下のようにロードします(パスは適宜読み換える)。

import numpy as np

def load(f):
    return np.load(f)['arr_0']

# Load the data
x_train = load('kmnist/kmnist-train-imgs.npz')
x_test = load('kmnist/kmnist-test-imgs.npz')
y_train = load('kmnist/kmnist-train-labels.npz')
y_test = load('kmnist/kmnist-test-labels.npz')

# shapeを確認
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)
# => ((60000, 28, 28), (10000, 28, 28), (60000,), (10000,))

列ごとに10クラス(["お", "き", "す", "つ", "な", "は", "ま", "や", "れ", "を"])それぞれの文字を表示させてみましょう。

import matplotlib.pyplot as plt
%matplotlib inline

fig,axes = plt.subplots(nrows=10, ncols=10, figsize=(12, 12))
for r in range(10):
    data = x_train[y_train==r]
    for c in range(10):
        axes[r, c].axis("off")
        axes[r, c].imshow(data[c])

KMISTのクラスごとの画像
KMISTのクラスごとの画像

"つ", "は", " を"など、同じクラス内でも2パターンの書き方があるように見えますね。

4. t-SNEによる次元削減

識別を行う前に、ざっと2次元への次元削減を試してみましょう。計算量の関係で、ここでは先頭1000個のみ扱うことにしました。

from sklearn.manifold import TSNE

# shape (60000, 784) に変換
X = x_train.reshape(x_train.shape[0], -1)

# 先頭1000個を2次元に削減
tsne = TSNE(n_components=2)
X_embedded =tsne.fit_transform(X[:1000])

2次元に削減されてshapeが(1000, 2)になったX_embeddedが計算できました。

散布図で可視化してみましょう。

labels = ["お", "き", "す", "つ", "な", "は", "ま", "や", "れ", "を"]

for i in range(10):
    emb = X_embedded[y_train[:1000]==i]
    marker = "$" + str(i) + "$"
    plt.scatter(emb[:, 0], emb[:, 1], marker=marker, label=labels[i])
plt.legend()

KMNISTにt-SNEを適用した結果
KMNISTにt-SNEを適用した結果

5. CNN(by Keras)による識別

畳み込みニューラルネットでの識別を試みます。といっても、すでにKerasによるベンチマーク実装がGitHubに公開されているので、それを実行してみただけです。ソースコードはそちらを参照してください。

kmnist/kuzushiji_mnist_cnn.py at master · rois-codh/kmnist · GitHub

実行してみたところ、

  • Train accuracy: 0.9967
  • Test accuracy: 0.9492

となりました。

同じ構造のCNNでは「普通の」MNISTに対して99%のTest accuracyがでるようなので、やはりそれに比べると難しい問題となっているようです。 完全に主観ですが、くずし字が結構ぐちゃぐちゃに見える割にはよく識別できているように感じました。

6. まとめ・今後のこと

ほとんどMNISTのように扱うことのできるくずし字データセットを触ってみました。 この記事で扱った10クラスのデータセット以外にも49クラスのものや漢字のデータセットも用意されており、そちらも近いうちに扱いたいです。 MNISTと同じぐらいの規模感で気軽に試せるデータセットの選択肢が増えたのは有難いですね。

以前紹介したOptunaでのチューニングも試してみたいところです。まだ富士山にしか使っていないので...

sw1227.hatenablog.com

以上

直感 Deep Learning ―Python×Kerasでアイデアを形にするレシピ

直感 Deep Learning ―Python×Kerasでアイデアを形にするレシピ