PythonからGraphvizを使う

環境はMacでPython3.5です。

Graphvizというdot言語を用いてグラフを作成するツールがあるので使ってみた。

インストール

# コマンドから使用するときは
brew install graphviz
# Pythonから呼び出したいときは
pip install graphviz

コード

from graphviz import *

G = Digraph(format="png") # 有向グラフ初期化
G.attr('node', shape='circle') # ノードの形

G.node("my","俺") # ノード作成

N =  1  # ノード数
for i in range(N):
    G.node("boss"+str(i),"ボス") 
    G.edge("boss"+str(i), "my" ) # edge(元, 先) で線をつなぐ

print(G)
G.render('my') # 画像作成

pngファイルが生成される。

f:id:carumisu:20160623111815p:plain

機械学習でのCSVファイルの読み込み

Kaggleのチュートリアルを参考にした。

コードはPython3.5。

ロジスティック回帰

import csv
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn import metrics

def read_dataset(filename):
    csv_file_object = csv.reader(open(filename 'r'))
    # header = next(csv_file_object)
    x = []
    y = []
    for row in csv_file_object:
        x.append(row[:2])
        y.append(row[2])
    return (np.array(x), np.array(y))

# トレーニングデータ読み込み
X, Y = read_dataset("train.csv")
X = X.astype(np.float64)

# テストデータ読み込み
X_, Y_ = read_dataset("test.csv")
X_ = X_.astype(np.float64)

# ロジスティック回帰モデル 定義
lr = LogisticRegression()

# 学習
lr.fit(X, Y)

# 予測
score = metrics.accuracy_score(lr.predict(X_), Y)

# 正解率
print(str(score*100)+"%")

サポートベクターマシン

import csv
import numpy as np
from sklearn import svm
from sklearn import metrics

def read_dataset(filename):
    csv_file_object = csv.reader(open(filename, 'r'))
    # header = next(csv_file_object)
    x = []
    y = []
    for row in csv_file_object:
        x.append(row[:2])
        y.append(row[2])
    return (np.array(x), np.array(y))

# トレーニングデータ読み込み
X, Y = read_dataset("train.csv")

# テストデータ読み込み
X_, Y_ = read_dataset("test.csv")


# 学習
for kernel in ('linear', 'poly', 'rbf'):

    # SVMでの学習
    clf = svm.SVC(kernel=kernel, gamma=2)
    clf.fit(X, Y)

    # 正答率
    score = metrics.accuracy_score(clf.predict(X), Y)
    print(kernel,str(score*100)+"%")

TensorFlowつかってみた

Python3.5で書いてみた。

TensorFlow

TensorFlowは Googleが作った機械学習ライブラリのこと。 深層学習以外にも使える。 書いたコードからニューラルネットワークの可視化できるも便利。

コード

from helper import *

INPUT_SIZE = 2
CATEGORY_NUM = 1 # 出力ユニット数
LEARNING_RATE = 0.02
TRAINING_LOOP = 10000 # 学習回数
SUMMARY_DIR = 'test' # ログデータを保存するディレクトリ
SUMMARY_INTERVAL = 1000 # 途中経過の出力

# データセットの準備
X = np.array([[1.,3.],[3., 1.],[5.,7.]])
Y = np.array([190., 330., 660.]).reshape(3,1)
with tf.Graph().as_default():

    # 入力
    with tf.name_scope('input'):
        # 入力ベクトル
        x = tf.placeholder(tf.float32, [None, INPUT_SIZE], name='input_x')
        # 正解ラベル
        y_ = tf.placeholder(tf.float32, [None, CATEGORY_NUM], name='labels')

    # 出力
    with tf.name_scope('readout'):
        # 重みベクトル
        W = weight_variable([INPUT_SIZE, CATEGORY_NUM], name='weight')
        # バイアスベクトル
        b = bias_variable([CATEGORY_NUM], name='bias')
        # 出力ベクトル
        y = tf.matmul(x, W) + b

    # 誤差関数と更新するアルゴリズムの定義
    with tf.name_scope('optimize'):
        # 二乗誤差
        loss = tf.reduce_mean(tf.square(y_ - y))
        # パラメータ更新のためのアルゴリズム
        train_step = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(loss)
        loss_summary = tf.scalar_summary('loss', loss)

    # 学習
    with tf.Session() as sess:
        # ログデータを入れるファイルを開く
        train_writer = tf.train.SummaryWriter(SUMMARY_DIR + '/train', sess.graph)
        test_writer = tf.train.SummaryWriter(SUMMARY_DIR + '/test', sess.graph)

        # 正解率の計算
        correct_prediction = tf.equal(tf.sign(y), tf.sign(y_))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        train_accuracy_summary = tf.scalar_summary('accuracy', accuracy)
        test_accuracy_summary = tf.scalar_summary('accuracy', accuracy)

        # パラメータの更新
        sess.run(tf.initialize_all_variables())
        for i in range(TRAINING_LOOP + 1):
            sess.run([train_step], {x: X, y_: Y})

            # 途中経過の出力
            if i % SUMMARY_INTERVAL == 0:
                print('step %d' % i)
                summary = sess.run(tf.merge_summary([loss_summary, train_accuracy_summary]), {x: X, y_: Y})
                train_writer.add_summary(summary, i)
                summary = sess.run(tf.merge_summary([test_accuracy_summary]), {x: X, y_: Y})
                test_writer.add_summary(summary, i)

        # テストデータを入れてみる
        new_x = np.array([2., 4.]).reshape(1,2)
        new_y = sess.run(y, {x: new_x})
        print(new_y)

可視化

可視化するためのコマンドでtensorboardっていうものがあるんですが、引数にログデータの絶対パスを入れる必要がある。 いちいち打つのめんどくさいから、greadlink を使って絶対パスを取得した。

$ tensorboard --logdir=`greadlink -f test`
Starting TensorBoard b'16' on port 6006
(You can navigate to http://0.0.0.0:6006)

って出てくる。

そして、http://localhost:6006 にアクセスすると f:id:carumisu:20160601145120p:plain

と、出てくる。

今回は回帰問題を扱ってみた。

参考URL

TensorFlowでDeep Neural Networks (1) ロジスティック回帰 - Qiita

簡単な推薦システムを作ってみた

ある人の使用しているプログラミング言語から、次に学習すべきプログラミング言語の推薦システムを簡単に作った。

Python3.5でかいた。 参考書籍はこれ。

データサイエンティスト養成読本 機械学習入門編 (Software Design plus)

データサイエンティスト養成読本 機械学習入門編 (Software Design plus)

データ

データはこれ。

Ruby,Python,HTML/CSS/JS,C,C++,Java,PHP,C#
0,5,2,0,3,4,1,0
4,0,0,0,0,0,5,0
0,0,0,5,4,0,0,0
0,3,2,0,5,4,0,0
0,5,4,0,0,2,0,0
3,0,2,0,5,4,0,0
0,0,0,0,4,3,0,5
0,1,2,5,4,0,0,3
0,4,0,5,0,0,0,0
0,4,0,0,5,0,0,0
0,0,0,0,4,5,0,0
3,4,1,0,0,5,2,0
5,4,2,0,0,0,0,3
4,5,0,0,0,0,0,0
3,0,4,0,0,5,0,0
5,0,4,0,3,0,0,0
3,0,0,0,0,5,4,0
0,0,3,5,4,0,0,0
0,0,0,5,4,0,0,3
0,4,0,5,0,3,0,0
4,0,3,0,0,0,0,5
0,4,0,0,5,0,0,0

Twitterのフォロワーさんのプロフィールを元にデータを作りました。 プロフィールの一番左に書いてあるプログラミング言語を評価値を5として、右にいくにつれてデクリメント。

例えば、 C/C++/Ruby/JS なら Cの評価値を5、C++の評価値を4、Rubyの評価値を3、そしてJSの評価値を2みたいな感じで、最大5個まで評価値をつけていった。

書いていない言語は触ったことがないものとして、評価値を0にした。

コード

処理としては、推薦したい人が習得している言語と、似たような傾向を持った人が習得している言語を推薦している。

似てるか似てないかは、コサイン距離を用いて表現している。

# coding:utf-8

import numpy as np
import scipy as sp
from scipy.spatial.distance import cosine

def calc_item_score(target_user_index, user_rating_matrix):
    """
    指定したアイテムの評価値を計算する
    :param target_user_index: int: ユーザのIndex
    :param user_rating_matrix: numpy.ndarray: ユーザアイテムの評価値行列
    :return: float: 指定したアイテムの評価値
    """

    target_user_ratings = user_rating_matrix[target_user_index]
    item_similarity = np.zeros(len(target_user_ratings))

    for compare_user_index in np.arange(len(user_rating_matrix)):
        compare_user_ratings = user_rating_matrix[compare_user_index]
        if compare_user_index == target_user_index:
            # 同一ユーザのときは類似度計算はしない
            continue

        # ユーザの類似度をコサイン距離から求める
        user_similarity = 1.0 - cosine(target_user_ratings, compare_user_ratings)
        # 求めたコサイン距離をそのユーザの評価値に乗じて足しあわせる
        item_similarity += user_similarity * compare_user_ratings

    return item_similarity

# データ読み込み
data = sp.loadtxt("data.csv",delimiter=",",skiprows=1)

# 推薦計算
predict_ratings = calc_item_score(0,data)

# 推薦したい言語の取得
header = ['Ruby','Python','HTML/CSS/JS','C','C++','Java','PHP','C\#']
zero_index = np.nonzero(data[0,:] != 0)
for i in zero_index:
    predict_ratings[i] = 0.0
max_index = np.where(predict_ratings == predict_ratings.max())
print("次は ",end="")
print(header[max_index[0][0]],end="")
print(" をやるんやで")

実行結果

% python main.py
次は Ruby をやるんやで

となる。

サポートベクターマシンによる分類

Python3.5でやってみた

サポートベクターマシン

データと境界線との距離の最大化を戦略とする手法。

非線形変換により線形分離ができないものでも分類可能。

かなり精度が良く、いろんなところに使われている。

コード

# coding:utf-8

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn import svm
from sklearn import cross_validation

# データセット
X = np.c_[
          (1.3, .8),
          (1.2, .5),
          (1.3, 2.1),
          (-1.5, -1),
          (-1.4, -.9),
          (-1.3, -1.2),
          (-1.1, -.2),
          (-1.2, -.4),
          # --
          (1, -1),
          (.2, -2),
          (.5, -2.4),
          (.2, -2.3),
          (0, -2.7),
          (.4, -.7),
          (-.5, 1.2),
          (-1.5, 2.1),].T
# 正解ラベル
Y = [0] * 8 + [1] * 8

# 画面の数
fignum = 1

# 学習と描画
for kernel in ('linear', 'poly', 'rbf'):

    # SVMでの学習
    clf = svm.SVC(kernel=kernel, gamma=2)
    clf.fit(X, Y)

    # クリア
    plt.figure(fignum, figsize=(4, 3))
    plt.clf()

    # データセットのプロット
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=80,
                facecolors='none', zorder=10)
    plt.scatter(X[:, 0], X[:, 1], c=Y, zorder=10, cmap=plt.cm.Paired,s=100)

    # maxとmin
    plt.axis('tight')
    x_min = -3
    x_max = 3
    y_min = -3
    y_max = 3

    # 等高線を書くための準備
    XX, YY = np.mgrid[x_min:x_max:200j, y_min:y_max:200j]
    Z = clf.decision_function(np.c_[XX.ravel(), YY.ravel()])
    Z = Z.reshape(XX.shape)
    plt.figure(fignum, figsize=(4, 3))
    plt.pcolormesh(XX, YY, Z > 0, cmap=plt.cm.Paired)

    # 描画画面の設定
    plt.xlim(x_min, x_max)
    plt.ylim(y_min, y_max)
    plt.xticks(())
    plt.yticks(())
    fignum = fignum + 1


# plt.scatter(X[:8,0],X[:8,1],c="blue",s=100)
# plt.scatter(X[8:,0],X[8:,1],c="red",s=100)

plt.show()

f:id:carumisu:20160518155459p:plain

f:id:carumisu:20160518155506p:plain

f:id:carumisu:20160518155511p:plain

こんな感じです

matplotlib 複数のグラフを表示

# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np

# データ
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

# クリア
plt.close('all')

# どのように分割するかを行列で指定
f, ax = plt.subplots(2,2)

# それぞれの要素に描画
ax[0,0].plot(x, y)
ax[0,0].set_title('Simple plot')
ax[0,1].plot(-x, -y)
ax[0,1].set_title('Reverse Simple plot')
ax[1,0].plot(x, y)
ax[1,0].set_title('Simple plot')
ax[1,1].plot(-x, -y)
ax[1,1].set_title('Reverse Simple plot')

# 表示
plt.show()

f:id:carumisu:20160517093631p:plain

行列で指定できるの便利

参考URL

pylab_examples example code: subplots_demo.py — Matplotlib 1.5.1 documentation

回帰学習を簡単に実装してみた

Python3.5で教師あり学習の回帰の簡単な実装。

sinカーブを学習してみた。 パラメータの個数は1,3,5,7。

# coding: utf-8
import scipy as sp
import matplotlib.pyplot as plt

# 次元ごとに取得
x = sp.arange(0, 10, 0.1)
y = [ sp.sin(i) for i in x]
# NaNの除去
# x = x[~sp.isnan(y)] 
# y = y[~sp.isnan(y)]
# グラフに散布
plt.scatter(x,y)

# 学習(回帰)
fx = sp.linspace(0, x[-1], 1000)
f1 = sp.poly1d(sp.polyfit(x, y, 1))
f3 = sp.poly1d(sp.polyfit(x, y, 3))
f5 = sp.poly1d(sp.polyfit(x, y, 5))
f7 = sp.poly1d(sp.polyfit(x, y, 7))
# 描画
plt.plot(fx, f1(fx), c="red", linewidth=2)
plt.plot(fx, f3(fx), c="green", linewidth=2)
plt.plot(fx, f5(fx), c="blue", linewidth=2)
plt.plot(fx, f7(fx), c="pink", linewidth=2)

# グラフの設定と表示
plt.title("Title")
plt.xlabel("x label")
plt.ylabel("y label")
plt.xticks([w*7*24 for w in range(10)],
    ['week %i'%w for w in range(10)])
plt.legend(["d=%i" % f1.order, "d=%i" % f3.order, "d=%i" % f5.order, "d=%i" % f7.order], loc="upper left")
plt.autoscale(tight=True)
plt.grid()
plt.show()

こんな感じのグラフが出たらOK。

f:id:carumisu:20160516100015p:plain