gepuro.net
gepulog

データ分析エンジニアによる備忘録的ブログ

データサイエンスLT祭り 2夜目で発表してきました

久しぶりにLTをした気がします。少しだけ便利になると思うので、使ってもらえると嬉しいです。

Rstudio上でのパッケージインストールを便利にするaddin4githubinstall from gepuro

SQLite3をPythonから使っていたら「sqlite3.OperationalError: database or disk is full」というエラーが出た

タイトルの通りで頭を抱えていました。

Bashで

$ df -h

を実行してもディスクは溢れていなかったのです。

ググってみるとSQLITE3 VACUUM, “database or disk is full”という人がいたので覗いたら解決しました。

conn = sqlite3.connect("data.db")
cur = self.conn.cursor()
cur.execute("""
    pragma temp_store_directory='/tmp'
    """)
conn.commit()

のようにして、一時ディレクトリを指定したら動くようになりました。 デフォルトでは、どこに持ってるのだろうか?そこまでは調べていません。

また、

vacuum;

というのも覚えました。

SQLite3でデータを追加したり消したりするとゴミが溜まってくるそうで、それを削除出来るとのことです。

データベースが大きくなった時に活躍しそうなので、ついでにメモしておきます。

統計的学習の基礎4.4~を読みました

統計的学習の基礎読書会で発表してきました。以下がその時の資料です。

統計的学習の基礎 4.4~ from gepuro

ATOMで数式を改行する方法

動作環境は、mathjax-warapperを入れて、markdown-preview-plusでプレビューを確認している。

下の方法で改行出来た。

\[
\begin{align}
y &= x + x + x \\
&= 3 x
\end{align}
\]

Python3で「if a in b」をするときはsetを使うべし

タイトルの通りです。下のコードで確認しました。 データが増えてくると1万倍は変わるようです。

Python 3.5.1 |Anaconda 2.4.1 (64-bit)| (default, Dec  7 2015, 15:00:12) [MSC v.1900 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 4.0.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:import time
:
:a = [i for i in range(10000)]
:b = [i for i in range(5000,100000)]
:start = time.time()
:[i for i in a if i not in b]
:elapsed_time = time.time() - start
:print(elapsed_time)
:
:a = [i for i in range(10000)]
:b = set([i for i in range(5000,100000)])
:start = time.time()
:[i for i in a if i not in b]
:elapsed_time = time.time() - start
:print(elapsed_time)
:<EOF>
7.634490013122559
0.0005004405975341797

numpy上で平均を求める v.s. Pandasで平均を求める

計算の待ち時間が長く感じることが増えたので調べる 結論は、numpyのみで計算した方が早い。 以下で確認した。

Python 3.5.1+ (default, Mar 30 2016, 22:46:26) 
Type "copyright", "credits" or "license" for more information.

IPython 2.4.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:import numpy as np
:import time
:
:start = time.time()
:dt = np.array([0 for i in range(100)], dtype=float)
:for i in range(100):
:    dt += dt
:dt = dt/100
:elapsed_time = time.time() - start
:print(elapsed_time)
:
:import pandas as pd
:start = time.time()
:dt = np.array([0 for i in range(100)], dtype=float)
:dt_list = [dt for i in range(100)]
:pd.DataFrame(dt_list).mean()
:elapsed_time = time.time() - start
:print(elapsed_time)
:<EOF>
0.00039386749267578125
0.00755763053894043

Pandasのappendが遅くて萎えた話

あまりにも処理に時間がかかるので、下のコードで確認した。

gepruo@ubuntu$ ipython3
Python 3.5.1+ (default, Mar 30 2016, 22:46:26) 
Type "copyright", "credits" or "license" for more information.

IPython 2.4.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:import pandas as pd
:import time
:start = time.time()
:df = pd.DataFrame()
:for i in range(100):
:    df.append(pd.DataFrame([1,2,3]))
:elapsed_time = time.time() - start
:print(elapsed_time)
:
:
:start = time.time()
:def gen_data():
:    for i in range(100):
:        yield [1,2,3]
:df = pd.DataFrame([i for i in gen_data()])
:elapsed_time = time.time() - start
:print(elapsed_time)
:
:<EOF>
0.21839094161987305
0.0008673667907714844

たった100回のappendであっても約251倍も変わることが分かった。

『詳解 Apache Spark』出版記念イベントに参加しました

最近はSparkに触れていなかったのですが、日本語の情報も豊富になってきたのを感じました。 自分も書きたい。 ブログネタでやるかなあ。と思った一日でした。

データ分析業界の理想と現実 - Spark普及の歴史を添えて(下田倫大さん)

  • Spark登場時に私は夢とロマンを見ました!
  • 現実は厳しい・・・。
  • ガンガン使おう
  • 2013年: 大規模データ処理といえばHadoopで集計
  • 2014年: Sparkとの出会い, インドで使ってた
  • 第一印象: Python, Rのインターフェースがある!
  • 2015年: ブレインパッド社としてビジネスモデル的にSparkのメリットが大きくない
  • コンサル/SI は新しい技術導入が遅くなりがち
  • ニーズが必要
  • DeltaCubeという自社開発プロダクトで導入
  • 案件が効率化からイノベーションに変化

データマネジメントツールDeltaCubeでのSpark利用(師岡一成さん)

  • 2014年に触り始めた
  • 2015年に本格的に
  • DeltaCube: プライベートDMPのログからセグメントを作成ツール
  • 2014年に開発が始まり、リリースまで2年ぐらいかかった
  • 初期
    • 行動ログを手動で検索して、セグメントを作成
    • データサイズは数TB, presto, impalaを使った
  • 中期(2015年) * 機能的にマニアック路線
    • 広告運用の手間がかからないようにしたい
    • 自動でユーザをクラスタリング(DeltaCube)
    • Rtosterで自動ABテスト
    • ETL, MLlib
  • 現在
    • YARNとPrestoの二つはいやだけど、統一できず・・・
    • EMR上にPrestoクラスタを稼働
  • Sparkよ流行ってくれ

Dynamic Resource Allocation in Apache Spark(今井雄太さん, @imai_factory)

  • Sparkとの出会い
    • Amazon KinesisのConsumerとして
  • Spark運用の話
  • ワードカウントの例(scalaで)
  • DAG Scheduler
    • sc.parallelize()でRDDが出来る、分散して保持されるオブジェクト
    • Array⇒ParallelCollectionRDD⇒MapPartitionsRDD⇒ShuffledRDD⇒Array
  • Tasks > Executors
    • Executorsの数をダイナミックに変えてくれる
    • Tasksの応じて、増やしたり、減らしたり
  • Dynamic Resource Allocationのよさ
    • 投げられたJobに対して、動的にExecutorsを変えて、速度を上げる
    • 消さないとリソースが無駄になるので、消そう

Help me! Help me with DNN in Spark!!(石川 有さん)

  • Spark2.0に向けてDNNの拡張を進めるとあったが、見送られた
  • 誰か助けて!
  • MultilayerPerceptronClassifier
    • Spark1.5
    • L-BFGS
    • Sigmoid, Softmaxのみ
  • Regression対応が必要
    • ReLU, 恒等写像
    • L-BFGSではなくSGDに最適化アルゴリズムを変更する必要がある
    • AdaGrad, Adamなどを実装できるように更新処理を再設計
  • 現在のSGDは非効率で精度が悪い
    • Parallelized SGDとして再実装する必要がある
  • Drop-outもできない
  • CNNのような多次元配列の入力をサポートしていない
  • Bayesian Optimizationなどの自動チューニングアルゴリズムを追加するべき
  • 既存のPublic APIを変更するのを嫌う風土

scalatestでSpark StreamingのUnitを書く話(田中裕一さん)

  • 100万人のデータ分析(Sparkを含む)
  • API 300億回/日でもSparkが使える
  • Spark as a Service
  • StreamingのUnitが面倒
    • アプリケーション側で状態を保つため、Unitが組みづらい
    • Streamingは外部との接続が前提なためUnitが書きにくい
    • 複数のmicro-batchの集計結果などの書き方が難しい(window処理など)
    • やったこと
      • Unit側でStream作成、Unitでテストデータ作成⇒Streamへ、処理結果の出力
    • 処理部分と接続部分は切り分けて書く(出力部分の切り分けた方が良い)
    • どうやってStreamを渡すか
  • SparkでTestを書こう
  • 簡単に書けるけど、構造化を意識しないと汚いコードになっちゃうので注意

spark.ml の API で XGBoost を扱いたい!(小宮篤史さん)

  • SmartNewsのエンジニアをしてます
  • XGBoostを知っているひと⇒ 少数
  • Spark上でXGBoostを使ったことあるひと⇒ 会場でほぼいない
  • SparkXGBoost
    • pure Scalaで実装
    • 開発が活発ではない
  • xgboost4j-spark
    • DMLCが提供する公式のSpark integration
    • RDDのみ、DataFrameに非対応

Sparkで始めるお手軽グラフデータ分析(加嵜長門さん)

  • Hadoop/Spark Conference Japan 2016でのアンケート
  • GraphXの利用ユーザが30人!(Spark SQL/ DataFrameは252人)
  • GraphFramesの登場
  • GraphXとDataFramesの統合
  • 1人3冊買えば、続編が出るかも!
  • グラフじゃないとできないの?
    • 多くの場合は他の選択肢がある
  • いろんな視点を持つことが大事
  • 社内営業をする時に、絵で説明できて良いこともある
  • リコメンド
    • ユーザ同士、商品間
  • マーケティング
    • ネットワークビジネス
    • バイラルマーケティング
    • 口コミを使ったマーケティング
      • 影響力の強いユーザの抽出
  • 不正検知
    • 偽装保険金詐欺
      • 少人数で何度も事故にあっているなんてことが・・・
    • クレジットカードの詐欺
      • 住所や電話番号を少人数で使いまわす
  • 会社間のお金の流れ
  • グラフDB
    • Neo4J, Titan
    • 分散処理による高スループット
  • グラフ処理系
    • GraphLab
    • グラフに特化しない汎用的なデータ構造
    • 表形式やベクトルとシームレスに結合できる
  • RDDから1行でグラフを作れる!

さいごに

アフィリエイトを張っておきます。

jqコマンドで正規表現を使う

日常的に利用しているjqコマンドですが、最新バージョンを入れれば正規表現が使えると知ったので、インストールしました。 OSはubuntu 14.04です。

基本的には、 https://stedolan.github.io/jq/download/に従えばよいですが、正規表現を利用するには外部ライブラリのインストールが必要なようです。

下のようにしてインストールした。余分なライブラリが入っているだろうが、調査するのが面倒だったので、apt-cache search onigでヒットしたものを全部突っ込んだ。

sudo apt-get install libjruby-joni-java libonig-dev libonig2 libonig2-dbg lua-rex-onig lua-rex-onig-dev

あとは、公式の通りにインストールするだけ。

git clone https://github.com/stedolan/jq.git
cd jq
autoreconf -i
./configure --disable-maintainer-mode
make
sudo make install

手元の環境では、./configure --disable-maintainer-mode --prefix=/usr/local/をしておいたり、pacoを使ってインストールしています。

Dockerでapacheを使う

忘れそうなので、メモしておく。

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]