プロメモグラム

誰が見てもわかるような文章を目指す

当確率ではないランダム

サイコロのように当確率で目がでるのではなく、おみくじのように出現確率が変化するようなプログラムが必要になったので作成した。

実際にうまく言っているかを確認するため、ヒストグラムを表示させた。

weighted_random関数

  • 入力:Numpyの配列に重み付けをした数値を入れる(合計が1である必要はない)
  • 出力:ランダムな値(0~配列長-1)を返す
import numpy as np
import matplotlib.pyplot as plt

# 入力データ(それぞれ、10%,30%,60%)
data = np.array([0.1, 0.3, 0.6])

# 関数
def weighted_random(data):
    # 累積
    culm = [0] * data.shape[0]
    total = np.sum(data)
    for i in range(data.shape[0]):
        cuml[i] = np.sum(data[:i+1]) / total
    # 乱数から選択
    s = np.random.rand()
    m = 0
    for i in cuml:
        if s < i:
            break
        m += 1
    return m

# 表示
x = np.array([weighted_random(data) for _ in range(1000)])
plt.hist(x, rwidth=1.0, bins=3)

f:id:zia_glass:20171125214942p:plain

1000個の結果から見て大体100個、300個、600個程度の出力を得ている。 なんかもっと綺麗に書けないんだろうか。

irisデータセットでOneClassSVM

One-Class SVMは1つのラベルでモデルを生成する。
RBFカーネルを用いることで、実行結果のように取り囲む識別面ができる。

実行結果

gamma = 0.1

f:id:zia_glass:20171008005341p:plain

gamma = 1.0

f:id:zia_glass:20171008005352p:plain

実行

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

def iris():
    iris = datasets.load_iris()
    X = np.hsplit(iris.data[0:100], [2])[0]
    y = iris.target[0:100]
    return(X, y)

X, y = iris()
colordic = ['red', 'green', 'g']
colors_map = map(lambda x: colordic[x] , y)
colors = [x for x in colors_map]


"""
gamma = 0.1
"""
#one-class svm
clf2 = svm.OneClassSVM(nu=0.1, kernel="rbf", gamma=0.1)
clf2.fit(X[:50, :])
#scatter
plt.scatter(X[:,0], X[:,1], color=colors)
#mesh
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.05),\
     np.arange(y_min, y_max, 0.05))
# contour
Z = clf2.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.5)
plt.show()


"""
gamma = 1.0
"""
# one-class svm
clf1 = svm.OneClassSVM(nu=0.1, kernel="rbf", gamma=1.0)
clf1.fit(X[:50, :])
#scatter
plt.scatter(X[:,0], X[:,1], color=colors)
#mesh
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.05),\
     np.arange(y_min, y_max, 0.05))
# contour
Z = clf1.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.5)
plt.show()
     

markdown-preview-enhancedのスタイル

Markdownを書くときはVSCodeとかKobitoでも書けるけどAtomが便利な気がする。

VSCodeはコード書くように行数表示やVimプラグイン入れているから文章入力には向かない。 Kobitoでもローカルで保存できるけど、もっとシンプルにDropbox上のディレクトリで管理したい。

AtomだとプラグインいれるとKobitoみたいにコードのシンタックスハイライトやプレビューとのスクロール位置の同期をしてくれたり、リストを作る時のハイフンも改行時に自動で入力してくれたりするから、総合的に考えてAtomに行き着いた。

パッケージ

  • markdown-preview-enhanced
    • プレビューを良くしてくれる。数式や図式実は対応しているみたい。
  • markdown-writer

日本語がスペルチェック機能によって赤い下線引かれてしまうのが目障りなので、Core-Packageからspell checkを無効にした。

スタイル

Ctrl+Shift+P入力後 "markdown-preview-enhanced: customize css" でmarkdown-preview-enhanced専用のcss設定ができる。

html body {
  @main_color: #303030;
  @inverce_color: #eeeeee;

  background: @inverce_color;

  h1,h2,h3,h4,h5,h6 {
    color: @main_color;
  }

  h1 {
    font-size: 2.0m;
    text-align: center;
  }

  h2 {
    font-size: 1.7em;
    border-bottom: 1px solid @main_color;
  }

  h3 {
    font-size: 1.5em;
    text-decoration: underline;
  }

  h4 {
    font-size: 1.3em;
  }

  p, li {
    color: @main_color;
    line-height: 2em;
  }

  table {
    tr {
      background-color: @inverce_color;
      th, td {
        color: @main_color;
        border: 1px solid @main_color + #888;
      }
      th {
        background: @inverce_color - #222;
      }
    }
  }
}

Link

Google CalendarのStylishの設定

Googleカレンダーで一番左を月曜日にすると、
休日がまとまって嬉しいんだけど、
普通のカレンダーは一番左が日曜日だから、
曜日と日付の対応を間違える。

そこで、Chrome拡張機能Stylishを使って、
土日の背景色を変えた。

Stylishはスタイルの同期してくれないみたいだから、 メモっておく。とても簡単だけど多少よくなった。

.st-bg-table tbody tr :nth-child(6) {
    background-color : #aaf !important;
}
.st-grid  tbody tr :nth-child(6) {
    background-color : #aaf !important;
}

.st-bg-table tbody tr :nth-child(7) {
    background-color : #faa !important;
}
.st-grid  tbody tr :nth-child(7) {
    background-color : #faa !important;
}

f:id:zia_glass:20170730223722p:plain

Ubuntu導入時に個人的にやることまとめ

なんどかLinuxを導入する機会があるんだけど、そのたびに同じことを調べているような気がするので、 やることをまとめておく。思い出しつつ追加する形で。

環境は以下の通り

  • Ubuntu16.04 LTS (trusty)
  • GNOME shell

諸々をインストー

Lubuntuなどでは、まさかのvimが入っていないのでインストールをする。luaなどは使ってないので普通にaptで入れる。

sudo apt install -y git vim
sudo apt install ubuntu-restricted-extras

あとは、ネットからこいつらをダウンロードして、dpkgでインストール。

zshのインストー

うまく行かない時は、/etc/shellsにzshのパスが追加されていないかもしれない。

sudo apt install zsh
sudo chsh -s $(which zsh)

dotfilesを適用

管理しているdotfilesを適用(ここは本当に個人用)

git clone https://github.com/b1013251/dotfiles ~/dotfiles
bash ~/dotfiles/setup.sh

GNOME shellのインストー

個人的にGNOME shellのほうが好きなのでGNOMEを入れる。今後はデフォルトでGNOME shellになるらしい。 tweak toolも便利なのでインストールする

sudo apt install gnome-tweak-tool
sudo apt install gnome-shell-extensions
sudo apt install gnome-shell

便利なエクステンションをTweakToolをつかって入れる。 Put windowはWin+矢印で横幅を任意の長さに切り替えてくれるツール。 もともとのキーバインドがかぶるので、元の設定を、「設定」→「キーボード」から削除

  • Dash to dock
  • Alternatetab
  • Put window
  • Suspend button

また、TweakToolから以下の部分を設定

  • アニメーションを止める
  • 見た目が綺麗なPaperに変更
    • ここを参照してインストール+TweakToolから設定
  • CapsLockをCtrlとして扱う
  • 日付表示

Rubyをインストー

rbenvでインストール。必要なパッケージをaptで入れる。入れないと長いビルド中に怒られて異常終了する。
ディストリビューションHome · rbenv/ruby-build Wiki · GitHubを参照

sudo apt install -y autoconf bison build-essential libssl-dev\
libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev\
libffi-dev libgdbm3 libgdbm-dev

gitでrbenvとrbenv-build入れる。rbenvだけではRubyをインストール導入できない。

git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

PATHを通す。.zshrcで~/.zshlocalという名前を個人的にsourceしているので、そこに追加。

: ruby
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

Rubyをビルド

rbenv install -l
: 最新のバージョンを入れる
rbenv install 2.4.1
rbenv global 2.4.1

Pythonのインストー

Anacondaが便利なので、Anacondaを使って入れる。bashでインストール。 とりあえず、最新のPythonが入るので環境などは作らなくてもいい。

: 最新のものを入れる
bash Anaconda3-4.4.0-Linux-x86_64.sh
: 環境を作成(tensorflowを入れる場合は現状はPython3.5で対応しているので3.5を入れる)
conda create -n [環境名] python=3.5 anaconda

.zshlocalに追加

# anaconda
export PATH=$HOME/anaconda3/bin:$PATH

Node.jsをインストー

nodebrewをつかう

curl -L git.io/nodebrew | perl - setup
nodebrew ls-remote
: 最新を入れる
nodebrew install-binary v7.10.1
nodebrew use v7.10.1

pythonに機械学習系のライブラリを入れるとき必要なパッケージ

ライブラリを入れるときに先に入れる必要があるものリスト.

: #scipy
sudo apt-get install libatlas-base-dev
sudo apt-get install libatlas-doc

: #matplotlib
sudo apt-get install pkg-config 
sudo apt-get install libfreetype6
sudo apt-get install libfreetype6-dev
sudo apt-get install libpng-dev

anacondaが便利すぎて忘れてたけど
入ってないとエラーが出るし,そのたびに検索するのが面倒だったりする.

線形回帰のカーネルトリック

SVMに取り掛かる前に線形回帰のカーネルトリックを試す

前提

関数は以下のものにノイズを加える

$$ y=x3+\epsilon $$

見ての通り線形回帰だとうまくいきそうにないのでガウシアンカーネルで回帰を行う

また、コスト関数には誤差の総和を用い解析的に解く

まずは線形回帰

import numpy as np
import matplotlib.pyplot as plt

size = 25 #サンプル数
x = np.linspace(-6, 6, size) 
y_truth= (-0.05 * x ** 4) + ( 0.1 * x ** 3) + (-0.5 * x ** 2) + (0.6 * x )
np.random.seed(0)
y_noise = y_truth + np.random.randn(size) * 10.0

plt.plot(x, y_truth, color='#aaaaaa')
plt.scatter(x, y_noise, color="#aaaaaa")

w = (1 / np.dot(x, x) * x).dot(y_noise)
y_predict = w * x
plt.plot(x, y_predict, color="r")
plt.scatter(x, y_predict, color="r")

f:id:zia_glass:20170504022539p:plain

次に正則化していないカーネル

import numpy as np
import matplotlib.pyplot as plt

size = 25 # サンプル数
x = np.linspace(-6, 6, size) 
y_truth= x**3

np.random.seed(0) # ノイズ固定
y_noise = y_truth + np.random.randn(size) * 10.0

# 本来のデータ
plt.plot(x, y_truth, color='#aaaaaa')
plt.scatter(x, y_noise, color="#aaaaaa")

# ガウシアンカーネル
def kernel(x1, x2, beta=1.0):
    return np.exp(- beta * (x1 - x2)**2)

# グラム行列
K = np.zeros((size, size))
for i in range(size):
    for j in range(size):
        K[i,j] = kernel(x[i], x[j])
    
# 解析計算
alpha = np.linalg.inv(K) * y_noise

# 計算したパラメータをもとに予測
y_predict_kernel = np.zeros(length)
for _x, a in zip(x, alpha):
    y_predict_kernel += a * kernel(_x, _x)

# プロット
plt.plot(x, y_predict_kernel, color="b")
plt.scatter(x, y_predict_kernel, color="b")
plt.xlim([-6,6])
plt.ylim([-50, 50])

f:id:zia_glass:20170504022544p:plain

予想通りぐちゃぐちゃ

正則化を行って計算

size = 25 # サンプル数
x = np.linspace(-6, 6, size) 
y_truth= x**3

np.random.seed(0) # ノイズ固定
y_noise = y_truth + np.random.randn(size) * 10.0

# 本来のデータ
plt.plot(x, y_truth, color='#aaaaaa')
plt.scatter(x, y_noise, color="#aaaaaa")

# ガウシアンカーネル
def kernel(x1, x2, beta=1.0):
    return np.exp(- beta * (x1 - x2)**2)

# グラム行列
K = np.zeros((size, size))
for i in range(size):
    for j in range(size):
        K[i,j] = kernel(x[i], x[j])
    
# 解析計算 (アルゴリズム的にはここに単位行列を足しただけ)
alpha = np.linalg.inv(K + np.identity(size)) * y_noise

# 計算したパラメータをもとに予測
y_predict_kernel = np.zeros(length)
for _x, a in zip(x, alpha):
    y_predict_kernel += a * kernel(_x, _x)

# プロット
plt.plot(x, y_predict_kernel, color="b")
plt.scatter(x, y_predict_kernel, color="b")
plt.xlim([-6,6])
plt.ylim([-50, 50])

f:id:zia_glass:20170504022535p:plain

正則化項が働いて多少汎化された。

それで

モデルを通常の線形パラメータとは違うものに置き換えていることや、ガウシアンカーネルの次元数が無限にあることにより、正則化による影響が直感的にわかりにくいけど、うまくはいっているみたい。