病みつきエンジニアブログ

機械学習、Python、Scala、JavaScript、などなど

TensorFlowを社内向けにざっくりLTして回帰した(+資料とか)

Googleが先日「TensorFlow」という機械学習ライブラリを発表していて、話題になっています。

さっそく今日社内で紹介LTしてきました。

「社内」のエンジニアの話で言うと、機械学習の会社ではないので、機械学習とかDeep Learningとかには深掘りして話していないです。もちろん、機械学習ライブラリとかも知らない、けど、「なんかGoogleからディープラーニングをOSSで出したって話題になっているぞ」っていう感じの人向けに話しています。

公式チュートリアルをちょっとだけ逸脱した線形回帰をやってみたサンプルもあります。

ちゃんと自動で微分できてます。

github.com

このライブラリ、結構良いなあと思うのは、Googleが使っているという実績力かなと思います。公開初日に「Googleのプロダクションに使ってるんで」の実績は、ちょっとずるい(厳密にどれくらい使ってるかはわからないけど)。

ライブラリ自体がどう良いかについては、きっと誰かがまとめてくれると思う。パフォーマンステストとかも。

個人的に気になるのは、分散環境での実行について。彼らのペーパーの中には、分散コンピューティングについていろいろ書いてあるっぽいんだけど(読んでない)、ライブラリ中に陽に機能はない気がする。有効グラフのやつなのかな。誰かチュートリアル書いてください。

流行るかどうかはわからないけど、Googleで使ってるって言われちゃうと、過不足はなさそう(か、不足があれば実装されていく、だろう)。 そろそろちゃんとDeepLearningを実装しながら勉強したいと思っていたので、今年の残りはTensorFlowやろうかなあと思っている。

dotfiles公開した+vim/zshのおすすめ設定とか

yamitzky/dotfiles

会社のPCを新調して、環境設定するタイミングだったので、いい機会だしdotfilesを公開した。 今までは自分のプライベートgitサーバーに置いてたんだけど。

やはり、公開すると、綺麗に書くようになるしいいなあという感じします。

これだけだとブログとして寂しいので、いくつか解説を。

homesickを使った

homesick という、ホームディレクトリ構築用のOSSを使いました。

/home以下にあるファイルだけシンボリックリンクが貼られる、という仕様。homeディレクトリを作らないといけないので、なんとなく不格好だけど、シンボリックリンク貼る対象が明確になってわかりやすいです。

brew-bundleはなくてもいい

rcmdnk/homebrew-file みたいな解決策があるのですが、あまりいらないかなと思います。

インストールしたいものをテキストファイル(例えば、Brewlist)に一覧に書いて、

brew install `cat Brewlist`

みたいな感じで叩いてあげると、自動でインストールできます。逆に、Brewlist的なものを出すには

brew list > Brewlist

サブ設定を分割

.zshrcや.vimrcがどうしても肥大化してしまうので、「alias.zsh」とか「plugin.vim」みたいな感じで分割して、ロードしてあげる仕様にした。

vimの設定について

気に入っているのが、

  • 移動がjkilのゆとり仕様
  • カラースキームはwombat
  • バックアップファイルは ~/.vim/tmp に吐き出す
  • Pythonの「# -- coding: utf-8 --」をコマンド化

zsh用便利関数

  • SHA1を作る関数 sha1
  • Macの通知をする関数 notify
  • 任意サイズのランダムな画像を作る randimg
  • ファイル更新があったら通知する quickwatch
  • :tabe って書くとvimが立ち上がる
  • cd..って書くと cd .. になる
  • その他、Python経由のサーバーとかJSONパースとかURLエンコードとか

便利なOSS

  • よく使うディレクトリへすぐに飛べる autojump
  • peco を使った履歴検索
  • zsh用補完の、zsh-completions
  • コマンドエラーがないかわかりやすい、zsh-syntax-highlighting

直したいところ

  • OS依存
  • オレオレソフトウェアのgithub公開

何かご意見あれば、リプライください!

そんじゃーね!

「メールの添付ファイルにパスワードかけて、別メールでパスワードを送る」に言いたいこと

(2015/8/29追記)

最初に代案だけ書いておくと、(メールで送る程度の秘匿性のものは)「Proself」みたいな別プロトコルを使う、です。
メールパスワードでは、パスワードに規約をつけることもできません。
また、この話は企業等においてのルール化の話です。


もう何年前のネタなんだろうという感じでもあるのですが、2015年現在もこの慣習はなくなっていないように感じます。 実際社会人になってからも、残念なことに一度言われたことがありますし(受け売りでしか喋れなかったんだと思いますが)、自分もやったことがあります。

そこで、いくつかのケーススタディーから「この方法に意味があるのか」そして「どういう方式がセキュアか」という話をします。

メールのアカウントが漏洩するケース

例えば、POP3アカウントのIDとパスワードが流出して、アカウントに不正ログインされてしまったと仮定します。

このケースの場合は、添付ファイルを含むメールも、添付ファイルのパスワードを含むメールも流出していることになるので、意味がありません

これらケースでセキュアにするとしたら、ZIPはメールで、パスワードは電話や手紙・口頭(=別のプロトコル)で通知する必要があります。

メールを誤送信するケース

例えば、メールを誤送信する確率が、仮に1%だとします。

そのとき、(当たり前ですが)「添付ファイルつきのメール」を誤送信する確率も、1%です。したがって、「添付ファイルそのもの」を誤送信する確率は、全く変わっていません。しかも、パスワードを送るメールアドレスをコピペしてたりすると、結局確率は変わっていないわけです。

そこで問題になるのは、ZIPファイルのパスワードに意味があるのか、という問題です。意味がないとは言わないのですが、数文字程度の英数字とか、辞書に含まれる単語とかを使ってしまうと一瞬で解読されますし(ブルートフォースアタックや辞書攻撃)、パスワードはいずれ解読されるリスクがありますので、流出した時点でアウトです。例えば、暗号化(ハッシュ化)されたデータベースであっても、漏洩するとニュースリリースを出したりします。

パスワードの解読にかかる時間を見てみると、Password Recovery Speeds というサイトでは、英文字だけの場合、Class Eのコンピュータ(Workstation)で10桁のパスワードでも、16日で解読が終わると書いてあります。

したがって、このケースで問題ないのは、解読するほど価値が大きくない情報の場合です(トイレの鍵、という比喩ですね)。

一つ補足すると、ZIPファイルのパスワードを解読されたところで、不正アクセス防止法には該当しないのではないかと思いますので、法律による保護を求めるのは厳しいと思います(判例あるのかな・・・?)。

どうするのが良いか?

“慣習”方式は、あまり意味がないということをつらつらと書いてきました。私は、この“慣習”は止めるべきであるという意見です。

なぜならば、これをセキュアな方式だと勘違いする人が一定数いて、本当に大事なデータを上記の方法で送ってしまい、漏洩するリスクを高めるからです。そして、より良い代案があるからです。

このようなやり方をちゃんとやろうとすると、記号を含むような15桁とかのパスワードを設定して、別のプロトコル(電話とか)を使ってパスワードを通知するべきだ、となります。面倒くさいですし、ルール化するのは困難であると思います。

代案というのは、例えば、Proselfのようなパッケージを使うというやり方があります。Proselfはユーザーにセキュアなパスワードを強制できますし、ZIPよりもブルートフォースの速度が落ちますし、ログも残ります。(サーバー自体が脆弱である可能性は残りますが、責任の所在は集約されます)

さらに本当にセキュアにするのであれば、中間者攻撃のリスクも懸念して、暗号化ハードディスクで授受をする、という方法もあります(笑)

まとめ

以上をまとめると、 「メールの添付ファイルにパスワードかけて、別メールでパスワードを送る」という方式に対して、まずは「あまり安全ではない」ということを認識する必要があります。

その上で、適切な方法を選択すべき、ということでした!

スパースな行列のPearson相関係数

Scipyには、ピアソン相関係数を計算するための関数、scipy.stats.pearson というものがあるのですが、残念ながらスパースな行列(scipy.sparse)には対応していません。

実際、実装を見てみると(stats.py)、

mx = x.mean()
my = y.mean()
xm, ym = x - mx, y - my

という実装があり、単純に実装すると疎行列としては効率が悪くなります。 仮にxが疎行列だったとして、x - mx は要素がほぼ -mx な密行列になってしまうからです。

これは、定義の\sum_{i=1}^{n}{\left( x_i-\bar{x} \right)\left( y_i-\bar{y} \right)} に当たりますが、式変形をすると、陽に平均を引く必要がなくなります。(Wikipediaより引用)

f:id:yamitzky:20150527150315p:plain

ということで、これをコードに直して、

import numpy as np
import scipy.sparse

def pearsons(a, b):
    if not (scipy.sparse.issparse(a) and scipy.sparse.issparse(b)):
        raise ValueError("only sparse arrays are supported")
    if a.shape != b.shape:
        raise ValueError("shape of sparse arrays must be same")
    if a.shape[0] != 1 or b.shape[0] != 1:
        raise ValueError("size of dimention 1 must be one")
    n = a.shape[1]
    a_sum = a.sum()
    b_sum = b.sum()
    nmr = n * a.multiply(b).sum() - a_sum * b_sum
    return (nmr /
            np.sqrt(n * a.multiply(a).sum() - (a_sum) ** 2) /
            np.sqrt(n * b.multiply(b).sum() - (b_sum) ** 2))

実際に検証してみると、以下のように同じ値になります。

import scipy.sparse
from scipy.stats import pearsonr

a = scipy.sparse.csr_matrix([1, 2, 1, 0, 1])
b = scipy.sparse.csr_matrix([1, 0, 1, 4, 2])

print pearsons(a, b) # -0.93250480824031368
print scipy.stats.pearsonr(a.toarray()[0], b.toarray()[0])[0] # -0.93250480824031379

Pandas経由でHiveQLを実行してDataFrameに簡単に入れる方法

Hive経由で集計した値を、Pandasからスムーズに使うための方法を紹介します。 "スムーズ"に、というのは、「CSVを経由しない」と言い換えてもらって大丈夫です

準備

ライブラリとして、DropboxPyHive と Clouderaの impyla が必要です。

PyHiveを使っている理由は、必要な手続きが短いのと、PEP-0249に準拠しているからで、impylaを使っている理由は、as_pandasというユーティリティ関数を使いたいだけです。 なので、必須でないといえば必須でないです。

Anacondaを使っている場合は、下記の手順でインストールできます。

pip install impyla
conda install -c https://conda.binstar.org/blaze pyhive

コード

from pyhive import hive
from impala.util import as_pandas

conn = hive.connect(host="localhost")
cursor = conn.cursor()
cursor.execute("SELECT * FROM table")
df = as_pandas(cursor)

df.describe()

で、df にPandasのDataFrameオブジェクトが入ります(impylaの代わりにhiveになっているだけ)。 そんじゃーね!

アメブロでソースコードとかを投稿する方法、またはGithub Flavored Markdownで投稿する方法

お疲れ様です(?)

私の所属する会社には「アメーバブログ」というものがあり、せっかくなら愛着のある自社製品を使いたいところですが、残念なことに プログラマー向けの機能は全然足りません*1。ということで、弊社のプログラマーは、プログラミング系の話題ははてなブログに書いたり、github.ioに書いたり、qiitaに書いたりする人が多い。

しかし! 公式ブログはさすがにアメブロなので、アメブロでもソースコードを投稿しやすくする方法 というのを考案してみました

事前準備

アメブロの投稿画面を「パワーアップした新エディタ」にしてください

f:id:yamitzky:20140511124810p:plain

設定方法は、投稿画面の「パワーアップした新エディタを使おう」をクリックするか、「基本設定>記事投稿画面>新エディタ」です。

アメブロを使わずに書く

タイトルからして真っ向から反抗している感じがしますが、アメブロを使わずに書きます

ソースコードを綺麗に書けるエディタなら何でもいいですが、例えばGithub Flavored Markdownなエディタを使って、まず記事を書きます。

例えばGFMarkdownEditorとかMarkdown Editorとか、「Github Flavored Markdown javascript」で検索して出てくるものとかがお勧めです。もしくは、これらをForkして自分好みのエディターを作ろう!\(^o^)/*2

f:id:yamitzky:20140511125825p:plain

アメブロに貼り付け

記事を書いたら、エディタのプレビュー画面をコピーして、アメブロにペーストするだけです。

f:id:yamitzky:20140511131320p:plain

これでストレスなく、アメブロに技術ネタを投稿できるようになりました!

*1:ターゲットの問題がありますので、これは至極真っ当なことです

*2:本当はQiitaを使いたいんですが、コード上のcssがオリジナルであると想定されること、そしてそのcssが、Qiita上で使用することを前提に書かれていることを想定されると考えると、この目的に使うべきでないと考えます。

jedi-vimでanacondaのパッケージを補完させる

jedi-vimという、vimで(賢く)Pythonの補完などをしてくれるプラグインがあります。vimPython書くなら必須かも、というレベル。

当たり前(?)の話ですが、pipでインストールしたようなPythonのパッケージ群も、賢く補完してくれます。

しかし、デフォルトで使用するPythonが、システムのPython(/usr/bin/python)らしく、必然的にシステムのpipでインストールしたものしか補完してくれません。

そこで、anacondaのpipでインストールしたものなども補完できるようにしてみました。

やり方

やり方は単純で、~/.vim/ftplugin/python.vimの中に、以下のスクリプトを書くだけ。

python << EOF
import os
import sys

home = os.path.expanduser("~")
path = home + "/anaconda/lib/python2.7/site-packages"
if not path in sys.path:
  sys.path.insert(0, path)
EOF

要するに、anacondaのsite-packagesをsys.pathに追加しているだけです。同じ要領で、パッケージのディレクトリを増やすことも可能でしょう。

(おまけ) virtualenvを使う

virtualenvで管理している場合は(anacondaの場合そんなことできるのかしらんけど)、jmcantrell/vim-virtualenvを使うとvirtualenv環境のpythonが使われるらしい。試してないので知らないけども。