ついに今日の午前11時半に新元号が発表されますね。
とりあえず PyTorch によるディープ・ラーニング (深層学習) で元号の予想を作ってみました。今までされていない予想方法がないかなと思って、 視覚的・見た目 を予想することにしました。既にされている人がいたらすみません。
方法
機械学習の、深層学習、ディープ・ラーニングの方法の一つ、敵対的生成ネットワーク (GAN) の DCGAN を用いて、元号を 見た目 視点で予想することにします。 字面 (じづら) というやつです。
テキスト情報・文字情報ではなく、元号の画像を用意して、GANで、それっぽいものをたくさん生成してみるというものです。
コードは aidiary (@sylvan5) さんの記事 PyTorch (12) Generative Adversarial Networks (MNIST) - 人工知能に関する断創録 をほとんど写しました。ありがとうございました。主に変更した部分を下で解説しました。
入力「元号」画像生成
TeX を用いました。
- rubyでTeXファイルを生成して
- TeXからPDF (dvipdfmx)
- PDFからPNG (ImageMagick)
の手順で作りました。rubyからTeXファイルを作るコードは
にあります。
- 元号は少ないので、画像を回転をランダムに100回かけて増やしました。
- TeXで
\rotatebox{度数法の角度}{文字列}
とすれば回転できます。
- TeXで
- 4文字の元号は省きました。たぶん次も2文字になるでしょうから。(244個)
- 24644 枚のPNGファイルを作成しました。
PyTorch によるディープ・ラーニングのコード
コードは aidiary (@sylvan5) さんの記事 PyTorch (12) Generative Adversarial Networks (MNIST) - 人工知能に関する断創録 をほとんど写したのですが、これは MNIST という28×28の画像の集合のためのものなので、サイズを合わせる必要があります。
線形なネットワークの後に、"たたみ込み" 層が2段になっていて、ここで ConvTranspose2d
(PyTorch のドキュメントへのリンク) により、どかんどかんとサイズが大きくなっていきます。ConvTranspose2d
クラスは中では F.conv_transpose2d
関数が使われています。
transposed convolution と言ったり、deconvolution と言ったりします。いわゆる「たたみ込み」の逆のことをするのです。たたみ込みは小さくなりますが、transposed convolution はその反対なので、小さいサイズから大きなサイズが出てきますね。使われるカーネルやストライドやパディングは、全く同じ概念です。それを逆に (行列の言葉で言えば「転置」にして) 使うだけです。
- カーネルのサイズ ($k$とおきます)
- ストライド(ずらしていく幅) ($s$とおきます)
- パディング ($p$とおきます)
によって、この層を通った後の各ユニットのサイズが決まります。
今は kernel サイズ$k$は4、ストライド$s$は2、パディング$p$は1にしているので、最初の入力サイズを 8×8 (縦横8ピクセルずつ) にします。横のサイズを $w$, 縦のサイズを $w$ とおくことにします。
そうすると、まず
\begin{align}
& (w - 1)\times s - 2 \times p + k \\
= & (8-1)\times 2 - 2 \times 1 + 4 \\
= & 16
\end{align}
となり1辺が16ピクセルの出力が出てきて、次に
$$ (16-1)\times 2 - 2 \times 1 + 4 = 32$$
となるので、最後に 32×32の画像ができあがるというわけです。
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.fc = nn.Sequential(
nn.Linear(62, 1024),
nn.BatchNorm1d(1024),
nn.ReLU(),
nn.Linear(1024, 128 * 8 * 8),
nn.BatchNorm1d(128 * 8 * 8),
nn.ReLU(),
)
self.deconv = nn.Sequential(
nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.ConvTranspose2d(64, 1, kernel_size=4, stride=2, padding=1),
nn.Sigmoid(),
)
initialize_weights(self)
def forward(self, input):
x = self.fc(input)
x = x.view(-1, 128, 8, 8)
x = self.deconv(x)
return x
この変更を discriminator にも行います。
また、64×64版も同様に、サイズに合わせたネットワークの変更を行います。
結果: 32×32
はじめは、縦横32ピクセルずつの画像でやりました。
コードはGoogle Colaboratory のノートをご覧ください。
epoch 51 ぐらいまでくると結構見えてきますね! でもちょっと見えにくいので解像度を上げてみました。
結果: 64×64
見えにくいのでもうちょっと時間をかけて、縦横64ピクセルの画像を作りました。
これもGoogle Colaboratory のノート を置いております。
epoch 1
epoch 16
epoch 26
epoch 41
epoch 51
まとめ
ここから皆様の心の目で、新元号の字面を見いだして下さい。
妻と心の目で見たところ、
底、風、民、顧、天、筆、鳳、亀、実
のような感じの漢字が見えました。
- 天筆 (てんぴつ)
- 鳳民 (ほうみん)
- 風鳳 (ふうほう)
- 天亀 (てんがめ) (店があるww)
- 実底 (じってい)
とかどうですか?!
では。Happy deep learning.
追記
当然ながら、外れましたね。
「和」はこれまで19回も出てきたので見えないこともありませんが、「令」は初登場ですので、この生成画像からは見えてきません。(むしろこのネットワークではそれが正常)