技術メモ

役に立てる技術的な何か、時々自分用の覚書。幅広く色々なことに興味があります。

Extream Learning Machineの簡単実装

あまり知られていないかも知れないが、Extream Learning Machineというニューラルネットの一種がある。
3層のニューラルネットなんだけど、通常のニューラルネットと違い、学習は出力層と中間層の重回帰で学習する。通常のようなバックプロパゲーションのような面倒なことはしない。
入力層と中間層の間の重みはランダムで良く、学習する必要がない。ただ通常より多くの中間層ニューロンを用意しておく必要がある。
イメージとしては特徴量を大量生成しておいて、分類に役に立ちそうな候補手を重回帰で選択するといった感じだろうか。重回帰なのでデータをまとめてオフラインでしか学習できない。
利点

欠点

  • オンライン学習ではない
  • 過学習の問題がありそう
import matplotlib.pyplot as plt
import numpy as np
import seaborn
seaborn.set_style("whitegrid")

mid_num = 200
train_num = 2000
test_num = 200
train = np.random.random([train_num, 2]) * 10 - 5
teacher = np.zeros(train_num)
for i in range(train_num):
    teacher[i] = 0 if np.linalg.norm(train[i]) < 3 else 1
test = np.random.random([test_num, 2]) * 10 - 5
predict = np.zeros(test_num)

def activation(x):
    return 1/(1 + np.exp(-x))

# learning
input_weight = np.random.random([2,mid_num])
mid = activation(np.dot(train, input_weight))
output_weight = np.dot(np.linalg.pinv(mid), teacher)

# predicting
mid = activation(np.dot(test, input_weight))
output = np.dot(mid, output_weight)
predict = map(lambda x: 1 if x>0.5 else 0, output)

for i in range(test_num):
    color = "r" if teacher[i] else "b"
    plt.scatter(*train[i], color=color)

circle = [(3*np.sin(x), 3*np.cos(x)) for x in np.arange(0, 6.29, 0.001)]
plt.plot(*zip(*circle), color="g")

plt.axis("square")
plt.show()

f:id:swdrsker:20170302225355p:plain

2系を使っているWindowsにtensorflow導入 (python2.7 + widows + tensorflow)

tensorflowを使いたいけどデフォルトでpython2系を使っていて困っていた。
幸いanacondaを使っていたので結果的には簡単に導入できたという話。
手順にすると簡単に見えるが、ここまで来るのに紆余曲折したから一応記録しておく。

OS:Windows10
Anaconda4.2.0 (python2.7.13)
bash: Git for Windows

pythonのバージョンを変更する

この手順が重要。
tensorflowはpython3系しか入らない。
もっと言うと2017年2月現在では3.5までしかサポートしていない。
(Anaconda3系の最新版は3.6!)
なので、バージョンを変更した環境を作ってやらないといけない
異なるバージョンのpythonを使うのは、anacondaを使っていれば簡単に実現できる。
pythonの仮想環境に関する話 - 技術メモ

conda create -n python3.5 python=3.5

そして環境に入る

source activate python3.5

パッケージをインストール

pip install tensorflow

以上、手順にすれば一瞬。

確認

本家サイトにも掲載されている確認用のスクリプトを試してみる。

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))

なんかすごく警告が出るけど、、、一応通ってる。



本家サイト:
Installing TensorFlow on Windows  |  TensorFlow

最強の素数チェッカーを作ってみた

前回の記事の最後に書いた、決定的な素数判定と確率的な素数判定をハイブリッドにしたら最強なんじゃないかという考えのもと、最強の素数判定器を作ってみた。
特にひねりはないが、最初に3桁まで(引数で指定可能)の素数リストを作っておいて、確率的な素数判定にかける前に合成数を弾くというやり方。
swdrsker.hatenablog.com


純粋なエラトステネスの篩やミラーラビン素数判定法と比べて、
精度的には、並のカーマイケル数では太刀打ちできないはずなので精度も向上。
時間的にも、ちょっとした合成数なら最初から弾かれるので一瞬。
数百桁で本当に素数のものが現れたらちょっと時間がかかるかもしれないってくらい。

import random
import numpy as np

class PrimeChecker:
    def __init__(self, list_limit = pow(10,3)):
        if list_limit < 5: list_limit = 5
        self.prime_list = self.set_prime_list(list_limit)
        self.list_limit = list_limit

    @staticmethod
    def set_prime_list(n):
        def mark(primes,x):
            for i in xrange(2*x, n+1, x):
                primes[i-2] = False
        primes = [(i%2!=0 and i%3!=0 and i%5!=0) for i in range(2,n+1)]
        primes[0] = primes[1] = primes[3] = True
        for x in xrange(7, int(np.sqrt(n+1))+1):
           if primes[x-2]: mark(primes, x)
        prime_list = []
        for i in range(n-1):
            if primes[i]: prime_list.append(i+2)
        return prime_list

    def is_prime(self, n):
        k = 50 # number of iteration times
        if n < self.list_limit: return True if n in self.prime_list else False
        for prime in self.prime_list:
            if n%prime == 0: return False
        else:
            s, d = 0, n-1
            while d%2==0: s,d = s+1, d/2
            while k > 0:
                k = k-1
                a = random.randint(1,n-1)
                t, y = d, pow(a,d,n)
                while t != n-1 and y != 1 and y != n-1:
                    y = pow(y,2,n)
                    t <<= 1
                if y != n-1 and t%2 == 0:
                    return False
            return True

if __name__=="__main__":
    pc = PrimeChecker()
    pc.is_prime(58427) # True

PrimeCheckerのインスタンス化の引数で素数リストの数の上限を決めるんだけど、
素数リストがデカすぎると
最初にインスタンス化する時に時間がかかるのと、リスト内の走査に時間がかかるので
実行時間的には、初期化する素数リストは3,4桁が使いやすそう。