Hatena::ブログ(Diary)

ぱたへね

2016-11-28

[][] coding matrix task 2.11.4 上三角行列を後退代入で解く

行列の勉強しているとでてくる謎の行列、上三角行列の問題。

上三角行列になっていると、下から順番に代入していくことで、Ax=bの形の解が簡単にも求められるのか。なるほど。

教科書のコードは良く分からなかったので、再帰で解くようにした。明らかに再帰の問題だ。

from dicvec import *

def triangular_solve_n(rowlist, b):
    def tri_solve_last(rowlist, b):
        """最後の一行だけ解く"""
        if len(b) == 0:
            return []

        # 一番下の行の計算
        blast = b[-1]
        row = rowlist[-1]
        x = blast / row[-1]

        # 計算結果を元に行列を縮小
        row_new = []
        b_new = []
        for row, b_ori in zip(rowlist[0:-1], b[0:-1]):
            b_sub = row[-1] * x
            row.pop()
            row_new.append(row)
            b_new.append(b_ori - b_sub)

        return [x] + tri_solve_last(row_new, b_new)

    result = tri_solve_last(rowlist, b)
    result.reverse()

    return result


# ここから動作確認
v1 = [[1, 0.5, -2, 4],
     [0,   3,  3,  2],
     [0,   0,  1,  5],
     [0,   0,  0,  2]]

b1 = [-8, 3, -4, 6]

s = triangular_solve_n(v1, b1)
print(s)

v2 = [[2, 3, -4],
      [0, 1, 2],
      [0, 0, 5]]

b2 = [10, 3, 15]

s = triangular_solve_n(v2, b2)
print(s)

v3 = [[1, -3, -2],
      [0, 2, 4],
      [0, 0, -10]]

b3 = [7, 4, 12]

s = triangular_solve_n(v3, b3)
print(s)

実行結果

[-67.0, 18.0, -19.0, 3.0]
[15.5, -3.0, 3.0]
[17.8, 4.4, -1.2]

動いてる。

2016-11-27

[][] coding the matrix task 2.6.9 凸結合で線を書く

2点が2要素のリストとして与えられた時、その2点を端点とする線分上に等間隔に並んだ点のリストを100個返すPythonのプロージャsegment(pt1, pt2)を書け。

pt = [3.5, 3], pt2 = [0.5, 1]の時に、その点を描画せよ。

問題通りに解いてないけど、こんなアルゴリズムで線が引けることに関心した。理屈は大学入試で習っているはずだが、実際にプログラムで見たのは初めて。

# coding the matrix
# task 2.6.9
from myplot import plot

period = 100

pt1 = [3.5, 3]
pt2 = [0.5, 1]

s = []

for a in range(period):
    alpha = (1.0/period) * a
    beta = 1.0 - alpha
    x = pt1[0] * alpha + pt2[0] * beta
    y = pt1[1] * alpha + pt2[1] * beta
    s.append((x, y))

plot(s, file='task2.6.9.png')

結果

f:id:natsutan:20161127213845p:image

2016-11-21

[][] coding matrix task 1.4.10 複素平面に絵を書く

画像を読み込んで一定の輝度未満のところを複素平面にプロットする。そこまでして複素平面を使いたいのか・・・

いつものついったんで。

f:id:natsutan:20161121222520p:image

コードはこちら

# coding matrix
# task 1.4.10
# 画像を読み込んで、輝度が120以下の点をプロットする
import itertools
from PIL import Image, ImageOps
from myplot import ploti

input_file = 'twittan.jpeg'
th = 120

# 空集合を作る
S = set()

img = Image.open(input_file)
img_gray = ImageOps.grayscale(img)
max_x, max_y = img.size

for x, y in itertools.product(range(max_x), range(max_y)):
    # 座標変換
    yval = img_gray.getpixel((x, y))
    y = max_y - y
    if yval < th:
        p = x + y * 1j
        S.add(p)

size = max(max_x, max_y)

ploti(S, xrange=[-size, size], yrange=[-size, size], file='task1.4.10.png')

2016-11-19

[]単純パーセプトロンの学習結果の可視化

やったこと

関西で行われている『チームで学ぼう!TensorFlow(機械学習)実践編』でひらがなを認識するNNを作って学習させました。実際に手を動かして学習データを見ることで、単純パーセプトロンの動きがわかったのでまとめました。

https://soleildatadojo.doorkeeper.jp/events/51951

参考URL

TensorFlow : ML 初心者向けの MNIST (コード解説)

http://tensorflow.classcat.com/2016/03/09/tensorflow-cc-mnist-for-ml-beginners/

ここにもっと詳しく書いてあるので、正確に知りたいたいならこっちを読んでください。学習データが綺麗なひらがななので、可視化の結果はMNISTよりは理解しやすくなりました。

TensorFlowでアニメゆるゆりの制作会社を識別する

http://kivantium.hateblo.jp/entry/2015/11/18/233834

自分で用意した画像データをTensorflowで使うやり方がわかりやすく書いてありました。参考になりました。

学習データ

勉強会で確実に素性のわかっているデータセットを用意したほうが良いとアドバイスを受け、まずはWindowのフォントから抜き出しました。

https://github.com/natsutan/chihayaburu/blob/master/tools/hiragana_gen/hiragana_gen.py

ネットワーク

MNISTのチュートリアルを変更して、ひらがなの数に対応できるように増やしました。

https://github.com/natsutan/chihayaburu/blob/master/release/softmax/chihaya_softmax.py

学習結果の可視化

学習結果はそのまま読みだすことができないので、sees.runの引数にほしい変数を与え、戻り値として受け取ります。

   acc, y_true, y_pred, W, b = sess.run([accuracy, y_true, y_pred, W, b], feed_dict={x: test_img, y_: test_label})
   print(acc)

   np.savetxt('W.csv', W, delimiter=',')
   np.savetxt('b.csv', b, delimiter=',')

numpyの配列で返ってくるのでsavetxtでcsvに変換しました。

パラメータのWは784x46の行列です。784は28×28の画素数、46は今回の認識で使ったひらがなの数です。つまり、ひらがなの数だけ28x28の行列があるのでそれを画像に変更しました。

色をそれっぽく見せるために試行錯誤していますが、PIL.Imageを使ってpngに落としました。見やすいように拡大しています。

    i = 0
    for Wn in W.T:
      img = Image.new('RGB', (28,28))
      for y in range(28):
        for x in range(28):
          v = Wn[y*28+x]
          v16 = min([int(v*500), 255])

          if v < 0:
            col = (-v16 // 2, -v16 // 8, -v16 // 8)
          else:
            col = (0, 0, v16)
          img.putpixel((x,y), col)
      imgx8 = img.resize((28*8, 28*8))
      img.save('weight/w_' + str(i) + '.png')
      imgx8.save('weight/w4_' + str(i) + '.png')

      i+=1

可視化の結果

TensorFlow : ML 初心者向けの MNIST (コード解説)と同じく、青くなっているところが正の値、赤くなっているところが負の値を示しています。

f:id:natsutan:20161119151113p:image

f:id:natsutan:20161119151114p:image

f:id:natsutan:20161119151115p:image

f:id:natsutan:20161119151116p:image

f:id:natsutan:20161119151117p:image

MNISTよりは何をやっているかがわかりやすいのではないでしょうか。「い」がわかりやすいです。

これと識別したい文字画像を比較して、青いところに文字があれば高い点を、赤いところに文字があればマイナスの点をつけます。最終的に全画素の点を合計した値にバイアス(b)を足したものがスコアになります。46文字全てに同じ計算を行い、一番高い値が単純パーセプトロンが認識した文字になります。

気がついたこと

  • フォントの文字のように、綺麗なデータ、かつ位置決めがしかりできるなら単純パーセプトロンでも十分な精度がだせる。
  • 「い」がわかりやすいが、「い」の右側が学習結果の位置からずれると「い」と認識されない。平行移動や拡大、縮小に弱い。学習データを増やす必要がある。CNNではどうやって回避しているのかが気になる。
  • 学習、識別に使うデータが、白地に黒よりも、黒地に白の方が認識率が高い。Wx+bを大きくすることを考えた時に、黒い部分(輝度0)に重みをかけて大きな値に持っていくのが難しいからではないかと思う。僕の環境では、白地に黒だと86%、黒地に白だと91%の認識率。
  • 仕組みを理解するためには、自分でデータを用意したほうが良い。
  • CやVerilogでアルゴリズムを実装しようとすると仕組みがよくわかる。この程度であれば、重みは整数でも精度は変わらない。

2016-11-10

[][] coding matrix task 1.4.1 複素平面の描画

coding matrix読み始めました。

せっかくなので、自分でグラフ書いてみました。ライブラリはここ。

https://github.com/natsutan/matrix/blob/master/chap1/myplot.py

Pythonで虚数はjを使います。(知らなかった)

# coding matrix
# task 1.4.1
from myplot import ploti

S = {2+2j, 3+2j, 1.75+1j, 2.25+1j, 2.75+1j, 3+1j, 3.25+1j}

ploti(S, size=4, file='task1.4.1.png')

結果はこうです。

f:id:natsutan:20161110110346p:image