RubyでMnistを表示しつつ、４次元の不思議さを感じる

2019/01/11 追記
RubyからMNISTを利用したい人はRed Datasetsがおすすめです。
[RubyでMNISTやCIFAR-10を呼び出すRed Datasetsを使ってみる](https://qiita.com/kojix2/items/41fec8ec264c26e261bf)

RubyでMNIST画像を表示する方法はたくさんあると思います。しかし、ここでは敢えてわかりやすさを捨てて、[NArray](https://github.com/ruby-numo/numo-narray)の行列計算の威力に頼ることにします。配列の形を変えて、並び替えることでMNIST画像をタイルのように並べて表示しようという方針です。画像ファイルの作成は[MiniMagick](https://github.com/minimagick/minimagick)を使うことにしました。Mnistのデータは[red-chainer](https://github.com/red-data-tools/red-chainer)で呼び出しました。

```ruby
require 'chainer'
require 'mini_magick'

x, t = Chainer::Datasets::Mnist.get_mnist

pixels = Numo::NArray.concatenate(Array.new(100) { |i| x[i][0] })
pixels = pixels.reshape(10, 10, 28, 28).transpose(0, 2, 1, 3)
str = Numo::UInt8.cast(pixels * 255).to_string

img = MiniMagick::Image.import_pixels(str, 280, 280, 8, 'gray', 'png')
img.write('output.png')
```

![output.png](https://qiita-image-store.s3.amazonaws.com/0/144608/7cb17f2f-e78f-3eb3-322f-c17373e55da3.png)

…途中の行列の転置、おわかりいただけたでしょうか。これだけでわかってしまう人はものすごく数学に強い人だと思います（当社比）。

同じ処理をもっとわかりやすく書くと、こんな感じだと思います。

```ruby
require 'chainer'
require 'mini_magick'

x, t = Chainer::Datasets::Mnist.get_mnist

pixels = Numo::DFloat.zeros(280, 280)

10.times do |i|
  10.times do |j|
    pixels[i * 28...(i + 1) * 28, j * 28...(j + 1) * 28] = x[i * 10 + j][0].reshape(28, 28)
  end
end

str = Numo::UInt8.cast(pixels * 255).to_string

img = MiniMagick::Image.import_pixels(str, 280, 280, 8, 'gray', 'png')
img.write('output.png')
```

実は、私の場合、reshape や transposeをどうすれば、正しいMNISTの画像が生成できるか、よく考えてもわかりませんでした。
３次元でもわからないのに、４次元になると、本格的に何もわからなくなります。わかる人は尊敬します。

そこで、考えるのはやめて総当りです。permutationを使います。

```ruby
require 'chainer'
require 'mini_magick'

x, t = Chainer::Datasets::Mnist.get_mnist

pixels = Numo::NArray.concatenate(Array.new(100) { |i| x[i][0] })

[28,28,10,10].permutation.each do |a|
  [0,1,2,3].permutation.each do |b|
    pixels = pixels.reshape(*a).transpose(*b)
    str = Numo::UInt8.cast(pixels * 255).to_string

    img = MiniMagick::Image.import_pixels(str, 280, 280, 8, 'gray', 'png')
    img.write('png/output#{a}#{b}.png')
  end
end
```

この総当りの過程で生成されたMNistの画像がとても味わい深かったので、いくつかここに載せます。

![output[10, 10, 28, 28][0, 1, 3, 2].png](https://qiita-image-store.s3.amazonaws.com/0/144608/03f1eebb-5a91-498a-3c67-1efe2b947d88.png)![output[10, 10, 28, 28][0, 2, 3, 1].png](https://qiita-image-store.s3.amazonaws.com/0/144608/1b8c3904-b1aa-2d53-f3b3-7fdf42c3b1b0.png)![output[10, 10, 28, 28][2, 0, 3, 1].png](https://qiita-image-store.s3.amazonaws.com/0/144608/d1dda186-772d-4412-e6d8-1c57cf312db3.png)![output[10, 10, 28, 28][2, 3, 0, 1].png](https://qiita-image-store.s3.amazonaws.com/0/144608/320c4a19-1f50-8546-e53c-5b3232bdf009.png)![output[10, 10, 28, 28][3, 2, 1, 0].png](https://qiita-image-store.s3.amazonaws.com/0/144608/246752d1-467d-3c98-7b48-3a60d15b0cab.png)![output[10, 28, 10, 28][0, 1, 3, 2].png](https://qiita-image-store.s3.amazonaws.com/0/144608/eb926f0a-8a2f-3643-e55f-022c218a3f8f.png)![output[10, 28, 10, 28][1, 3, 0, 2].png](https://qiita-image-store.s3.amazonaws.com/0/144608/14707b4e-faac-7b22-c269-b2bde848b1ce.png)![output[10, 28, 10, 28][2, 3, 1, 0].png](https://qiita-image-store.s3.amazonaws.com/0/144608/4eba8570-c9b7-0732-afcc-28b787f7f8d2.png)![output[10, 28, 10, 28][1, 3, 2, 0].png](https://qiita-image-store.s3.amazonaws.com/0/144608/9c1e400b-93ef-9022-f3cf-20095db73369.png)![output[10, 28, 10, 28][3, 2, 1, 0].png](https://qiita-image-store.s3.amazonaws.com/0/144608/98167331-1464-2958-a628-c12a89cd3a4a.png)![output[10, 28, 28, 10][0, 2, 1, 3].png](https://qiita-image-store.s3.amazonaws.com/0/144608/e21ee286-1e1a-bea3-9992-fe6351e3b0db.png)![output[10, 28, 28, 10][0, 1, 3, 2].png](https://qiita-image-store.s3.amazonaws.com/0/144608/f0c55450-6e21-6aa4-ebd1-5088d838c9e0.png)![output[28, 28, 10, 10][2, 0, 1, 3].png](https://qiita-image-store.s3.amazonaws.com/0/144608/db53c5e8-6278-a006-0a85-a6c293e7045a.png)![output[10, 10, 28, 28][0, 1, 2, 3].png](https://qiita-image-store.s3.amazonaws.com/0/144608/222ca8de-9bec-5842-c543-94bc7053b4c1.png)![output[10, 28, 28, 10][2, 0, 1, 3].png](https://qiita-image-store.s3.amazonaws.com/0/144608/dcbf9c2a-28fc-51cb-22ad-25c3610c9783.png)![output[10, 28, 28, 10][3, 1, 2, 0].png](https://qiita-image-store.s3.amazonaws.com/0/144608/c73ee352-2ec6-729d-a9dd-b28a1ef4d7f3.png)![output[28, 10, 10, 28][0, 2, 1, 3].png](https://qiita-image-store.s3.amazonaws.com/0/144608/48747460-be33-cc77-ab57-746a0908eb90.png)![output[10, 28, 10, 28][3, 1, 0, 2].png](https://qiita-image-store.s3.amazonaws.com/0/144608/5202b6cc-e362-c5a9-6365-9a7e5df3449b.png)![output[28, 28, 10, 10][0, 3, 2, 1].png](https://qiita-image-store.s3.amazonaws.com/0/144608/40e20c54-e85d-73f4-ac92-8311981511cb.png)![output[28, 10, 10, 28][3, 0, 2, 1].png](https://qiita-image-store.s3.amazonaws.com/0/144608/845a1d26-27d1-348c-8fb6-cb63e8bfebbc.png)![output[10, 10, 28, 28][0, 2, 1, 3].png](https://qiita-image-store.s3.amazonaws.com/0/144608/f44a4e3c-2ba0-2562-cf4f-010c464930ac.png)

私が知ってるMNISTは右下だけです。けれども、驚くべきことに上の模様はすべてMNISTです。ただ4次元に持って行って、すこし配列の並び方を変えると、こんな不思議な画像が生成されてしまいました。はたして、今まで私は本当にMNISTを知っていたのでしょうか。それはMNISTの仮初の姿に過ぎなかったのではないでしょうか。

……

不思議な気分になったところで、本日はこの辺で失礼します。