洋食の日記

「だ・である」調ではなく「です・ます」調で書きはじめれば良かったなと後悔してる人のブログです

はてなブログProにしても広告を消すのには設定が必要だった

はてなブログProにすれば勝手に広告が消えると思ってたら、設定が必要だった。だいたい3ステップぐらい必要だった。広告を消したのは「広告って読み込み重いから鬱陶しいよね」という軽い気持ちから。

  • 設定から、詳細設定タブを選択する。

f:id:yoshoku:20170730094852p:plain

  • 広告を非表示で、はてなによる広告を表示しない、を選択する。

f:id:yoshoku:20170730094908p:plain

  • 画面最下部の変更するボタンを押すことを忘れずに。

f:id:yoshoku:20170730094923p:plain

以上。※画像がドーンってデカくなったので記事を後で修正しました。

MacではRubyのNMatrixでOpenBLASを使わなくてもLAPACKで十分に速かった

はじめに

Ruby線形代数機械学習アルゴリズムの実装を行う場合、SciRubyのNMatrixが最適だろう。 このNMatrixで、 RやPythonのNumpyと同様に、後ろで叩いているBLAS/LAPACKを、OpenBLASやIntel MKLに変えることで、高速化することを考えた。 しかし、Macでは、BLAS/LAPACKはAccelerate Frameworkに含まれていて、OpenBLASに変えるまでもなく十分に速かった。 環境は、MacBookIntel Core m3 1.1Ghz、メモリ8G、macOS Sierra 10.12.6 である。

行列積での実行速度の計測

まずは、素のNMatrixと、MacBLAS/LAPACKを使う場合の実行速度を計測した。 インストールは、gemからもできるが、測定条件を一致させるため最新版をビルドする方法を採用した。

$ git clone https://github.com/SciRuby/nmatrix.git
$ cd nmatrix/
$ bundle install
$ bundle exec rake compile nmatrix_plugins=lapacke
$ bundle exec rake spec nmatrix_plugins=lapacke
$ bundle exec rake install nmatrix_plugins=lapacke

単純な行列積で、実行速度を計測する。行列積が速くなると色々と嬉しい。

require 'nmatrix'
require 'benchmark'

Benchmark.bm do |x|
  x.report do
    50.times do
      a = NMatrix.random [1000, 1000]
      b = NMatrix.random [1000, 1000]
      c = a.dot b
    end
  end
end

これを、実行すると以下の様になる。

$ ruby test_nmat.rb
       user     system      total        real
  53.790000   1.400000  55.190000 ( 56.935680)

さらにLAPACKプラグインの実行速度を確認するため、require ‘nmatrix'を、

require 'nmatrix/lapacke'

と変更する。これを実行すると、素のNMatrixと比較してグンと速くなった。

$ ruby test_nmat.rb
       user     system      total        real
  23.050000   1.090000  24.140000 ( 18.840261)

OpenBLASに差し替えた場合での実行速度

OpenBLASは、Homebrewでインストールできる。 「–build-from-source」や「–with-openmp」といったオプションも指定できるが、 何も指定しないものが、行列積では最も速かった。

brew install openblas

「ext/nmatrix_lapacke/extconf.rb」を編集して、OpenBLASを使用するようにする。

...
#ldefaults = {lapack: ["/usr/local/lib"].delete_if { |d| !Dir.exists?(d) } }
ldefaults = {lapack: ["/usr/local/opt/openblas/lib"] }
...
#$libs += " -llapack "
$libs += " -L/usr/local/opt/openblas/lib -lopenblas "
...

NMatrixを再インストールする。

$ gem uninstall namtrix nmatix-lapacke
$ bundle exec rake clean
$ bundle exec rake compile nmatrix_plugins=lapacke
$ bundle exec rake spec nmatrix_plugins=lapacke
$ bundle exec rake install nmatrix_plugins=lapacke

OpenBLASを叩くLAPACKプラグインという状態なので、

require 'nmatrix/lapacke'

とする。実行してみると、LAPACKの結果と大差ないものとなった。

$ ruby test_nmat.rb
       user     system      total        real
  27.400000   4.530000  31.930000 ( 17.920017)

特異値分解での実行速度の計測

以下の特異値分解を含むプログラムでも比較を行った。

require 'nmatrix/lapacke'
require 'benchmark'

Benchmark.bm do |x|
  x.report do
    50.times do
      a = NMatrix.random [200, 2000]
      b = a.dot a.transpose
      #
      b.gesvd
    end
  end
end

LAPACKを使用した場合では、

$ ruby test_nmat2.rb
       user     system      total        real
   6.040000   0.300000   6.340000 (  5.908795)

となり、OpenBLASを使用した場合では、

$ ruby test_nmat2.rb
       user     system      total        real
  27.220000   4.920000  32.140000 ( 16.595134)

となった。OpenBLASよりもLAPACKの方が速く、 MacではAccelerate FrameworkのBLAS/LAPACKを使用した方が良いことがわかる。

ちなみに、Intel MKLでも試したが、Accelerate FrameworkのBLAS/LAPACKの方が速かった。 また、Intel MKLでは、rake spec した際にコケてしまった。

おわりに

MacでNMatrixを使用する場合は、

gem install nmatrix nmatrix-lapacke

として、

require 'nmatrix/lapacke'

とすれば良い。

Pandasで「ビジネス活用事例で学ぶデータサイエンス入門」を勉強する(第6章)

はじめに

マーケティング寄りのデータ分析の知識を補うため、以下の本で勉強を始めた。事例ベースな内容で、とても読みやすい。 Pandasも習得したいので、Pandasに翻訳しながら読み進めている。今回は第6章を勉強した。

ビジネス活用事例で学ぶ データサイエンス入門

ビジネス活用事例で学ぶ データサイエンス入門

ちなみに、CSVファイルなどのデータは、本のサポートページ(SBクリエイティブ:ビジネス活用事例で学ぶ データサイエンス入門)で配布されている。

翻訳したコード

第6章では、重回帰分析を扱っている。作業はJupyter Notebook上で行った。回帰にはScikit-Learnを用いる。 本ではひとまず、散布図を出力して、テレビ広告・雑誌広告とアプリのインストール数との関係を見ている。

%matplotlib inline # Jupyter Notebookでmatplotlibの図が表示されないときにつけるおまじない
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression

# データを読み込む。
ad_data = pd.read_csv('ad_result.csv')
ad_data.head(2)

 

month tvcm magazine install
0 2013-01 6358 5955 53948
1 2013-02 8176 6069 57300

 

# 散布図の出力にはscatterメソッドを用いる。
# x軸とy軸は、データのヘッダにある列名で指定できる。
ad_data.plot.scatter(x='tvcm', y='install')
ad_data.plot.scatter(x='magazine', y='install')

f:id:yoshoku:20170716150546p:plain f:id:yoshoku:20170716150557p:plain

散布図から何かしらの相関があることが伺える。回帰分析によりモデル化する。

# Numpy形式でデータを取り出す。
X=np.array(ad_data[['tvcm', 'magazine']])
y=np.array(ad_data['install'])

# 回帰モデルを得る。
model=LinearRegression().fit(X, y)

# 回帰モデルの切片と係数を確認する。
#  インストール数とテレビ広告・雑誌広告には以下の関係があることがわかる。
#  「インストール数 = 188.174 + 1.361 x テレビ広告 +7.250 x 雑誌広告」
print(model.intercept_)
print(model.coef_)
# 188.17427483
# [ 1.3609213   7.24980915]

# 決定係数を確認する。
#  1に近いので、当てはまりが良いことがわかる。
print(model.score(X,y))
# 0.937901430104

別の選択肢としては、StatsModelのOLS(Ordinary Least Squares)を用いる方法がある。 StatsModelの回帰分析は、summaryメソッドを持っており、R言語のlm関数に似た結果を得られる。

from statsmodels.regression.linear_model import OLS
results=model = OLS(y, X).fit()
print(results.summary())
#                             OLS Regression Results                            
# ==============================================================================
# Dep. Variable:                      y   R-squared:                       1.000
# Model:                            OLS   Adj. R-squared:                  0.999
# Method:                 Least Squares   F-statistic:                     8403.
# Date:                Sun, 16 Jul 2017   Prob (F-statistic):           5.12e-14
# Time:                        16:15:12   Log-Likelihood:                -84.758
# No. Observations:                  10   AIC:                             173.5
# Df Residuals:                       8   BIC:                             174.1
# Df Model:                           2                                         
# Covariance Type:            nonrobust                                         
# ==============================================================================
#                  coef    std err          t      P>|t|      [0.025      0.975]
# ------------------------------------------------------------------------------
# x1             1.3540      0.405      3.347      0.010       0.421       2.287
# x2             7.2892      0.476     15.320      0.000       6.192       8.386
# ==============================================================================
# Omnibus:                        1.009   Durbin-Watson:                   0.876
# Prob(Omnibus):                  0.604   Jarque-Bera (JB):                0.804
# Skew:                           0.539   Prob(JB):                        0.669
# Kurtosis:                       2.123   Cond. No.                         14.0
# ==============================================================================

おわりに

6章から、機械学習に関係する話がでてくる。PandasというよりもScikit-Learnが活躍する感じ。7章にある「本当の意味での正解データがないなかで、なんらかの(ビジネス上意味のある)示唆を出さなければならない」という記述は、「うっ」という苦しい気持ちになる。

Pandasで「ビジネス活用事例で学ぶデータサイエンス入門」を勉強する(第5章)

はじめに

マーケティング寄りのデータ分析の知識を補うため、以下の本で勉強を始めた。事例ベースな内容で、とても読みやすい。 Pandasも習得したいので、Pandasに翻訳しながら読み進めている。今回は第5章を勉強した。

ビジネス活用事例で学ぶ データサイエンス入門

ビジネス活用事例で学ぶ データサイエンス入門

ちなみに、CSVファイルなどのデータは、本のサポートページ(SBクリエイティブ:ビジネス活用事例で学ぶ データサイエンス入門)で配布されている。

翻訳したコード

第5章では、Web系のデータ分析では定番?のバナー広告のA/Bテストを扱っている。作業はJupyter Notebook上で行った。 カイ二乗検定が使われているが、Pandasにはカイ二乗検定はない様子なので、SciPyのstats.chi2_contingencyを使う。

%matplotlib inline # Jupyter Notebookでmatplotlibの図が表示されないときにつけるおまじない
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from scipy.stats import chi2_contingency

# データを読み込む。
ab_test_imp = pd.read_csv('section5-ab_test_imp.csv')
ab_test_goal = pd.read_csv('section5-ab_test_goal.csv')

# transition_idが同じものをくっつける。
ab_test_imp_goal = pd.merge(ab_test_imp, ab_test_goal, on=['transaction_id'], how='outer', suffixes=['','.g'])

# user_id.gがNaNだった場合に「0」それ以外では「1」として、クリックされたかを判定するフラグとする。
ab_test_imp_goal['is_goal'] = 1 - ab_test_imp_goal['user_id.g'].apply(np.isnan).astype(int)

# 集計してクリック率を計算する。
sum_goal = ab_test_imp_goal.groupby('test_case')['is_goal'].sum()
sz_user = ab_test_imp.groupby('test_case')['user_id'].size()
sum_goal / sz_user
# ※ Jupyter Notebook上には以下の用にクリック率が表示される。
#    Aが約8%で、Bが約11%となった。
# test_case
# A    0.080256
# B    0.115460
# dtype: float64

# カイ二乗検定により、クリック率に統計的な差があるかを確認する。
cr = ab_test_imp_goal.pivot_table(index='test_case',columns='is_goal', values='user_id', aggfunc='count')
# ※ crは以下のようなクロス集計結果となる
# is_goal    0        1
# test_case
# A          40592    3542
# B          38734    5056
#
chi2, p, dof, expected = chi2_contingency(cr.as_matrix())
print(chi2)
# 308.375052893
print(p)
# 4.93413963379e-69

chi2の値が本と同様の値となり、p値も本と同様にとても小さな値となった。 p値が小さいということで 「バナーAとバナーBでは、クリックされなかった(0)とクリックされた(1)の割合に差がない」という帰無仮説が棄却され、広告をバナーAとバナーBに分けたことで、クリック率が変わったと判断できる。 本では、この後、テストケースごとのクリック率を計算したりするが、今回は省略。

おわりに

Rのchisq.test関数と勝手が違ったので、手間取ってしまった。本ではカイ二乗検定の詳しい説明がないので、気になる方は別な統計本を買って勉強する必要がある。「統計的に有意な差」と「ビジネス的に意味があるか」という2つの観点が出てきたりして、ちょっと、この章は読みづらい感がある。

Pandasで「ビジネス活用事例で学ぶデータサイエンス入門」を勉強する(第4章)

はじめに

マーケティング寄りのデータ分析の知識を補うため、以下の本で勉強を始めた。事例ベースな内容で、とても読みやすい。 Pandasも習得したいので、Pandasに翻訳しながら読み進めている。今回は第4章を勉強した。

ビジネス活用事例で学ぶ データサイエンス入門

ビジネス活用事例で学ぶ データサイエンス入門

ちなみに、CSVファイルなどのデータは、本のサポートページ(SBクリエイティブ:ビジネス活用事例で学ぶ データサイエンス入門)で配布されている。

翻訳したコード

第4章では、クロス集計を扱っている。作業はJupyter Notebook上で行った。Pandasなコードは以下のとおり。

%matplotlib inline # Jupyter Notebookでmatplotlibの図が表示されないときにつけるおまじない
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# データを読み込む。
dau = pd.read_csv('section4-dau.csv')
user_info = pd.read_csv('section4-user_info.csv')

# user_idとapp_nameが同じものをくっつける。
dau_user_info = pd.merge(dau, user_info, on=['user_id', 'app_name'])

# 月次で集計するため、日付を月までにする。
dau_user_info['log_month'] = dau_user_info['log_date'].str.slice(0, 7)

# 性別で集計する。
dau_user_info.pivot_table(index='log_month',columns='gender', values='user_id', aggfunc='count')

 

gender F M
log_month
2013-08 47343 46842
2013-09 38027 38148

 

# 年代で集計する(表は省略)。
dau_user_info.pivot_table(index='log_month',columns='generation', values='user_id', aggfunc='count')

# 性別と年代で集計する(表は省略)。
dau_user_info.pivot_table(index='log_month',columns=['gender', 'generation'], values='user_id', aggfunc='count')

# デバイスで集計する(表は省略)。
dau_user_info.pivot_table(index='log_month',columns='device_type', values='user_id', aggfunc='count')

# 集計結果を可視化する。
dau_user_info.groupby(['log_date', 'device_type'])['app_name'].count().groupby('device_type').plot(legend=True,rot=45)

バイスでわけて、日付ごとのユーザー数を集計し、可視化したものが以下のとおり。 本と同様に、9月になってから、Androidユーザーが少なくなっている。

f:id:yoshoku:20170702213153p:plain

おわりに

pivot_tableで多重なクロス集計もできるので便利。今回も手こずったのは、plotの部分で、x軸のラベルを日付だけにしたかったけど諦め。細かいことは、matplotlib使えば良いんだろうけど、勉強中なので、しばらくはPandasのplotにこだわりたい。