u++の備忘録

PythonでRFM分析(任意のクラスタ数にK-meansクラスタリング)

やったこと

  1. RFMの3特徴量で各ユーザのデータを取得
  2. F, Mについては分布を考慮しlog10を取る
  3. データの可視化

サンプル

想定データ構造

UserID Recency Frequency Monetary (K-meansResult)
000000 123 456 789 0
000001 378 764 924 0
000002 578 267 532 1

Pythonコード

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import pandas as pd
df = pd.read_csv('df.csv')

import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

df.iloc[:,2] = np.log10(df.iloc[:,2]+1)
df.iloc[:,3] = np.log10(df.iloc[:,3]+1)

CLUSTERS_NUM = 5
pred = KMeans(n_clusters=CLUSTERS_NUM).fit_predict(df.iloc[:,1:4])
df = pd.concat([df, pd.DataFrame(pred)], axis=1)
fig = plt.figure()
ax = Axes3D(fig)
ax.set_xlabel("Recency")
ax.set_ylabel("Log10(Frequency)")
ax.set_zlabel("Log10(Monetary)")
d = []
for cluster_i in range(CLUSTERS_NUM):
    d.append(df[df.iloc[:,4]==cluster_i])
    c = cm.hot(float(cluster_i) / CLUSTERS_NUM)
    ax.plot(d[cluster_i].iloc[:,1], d[cluster_i].iloc[:,2], d[cluster_i].iloc[:,3], "o", color=c, ms=2, mew=0.5)
plt.show()

有料課金しているWebサービス一覧 (Jan, 2018)

自分の家計簿管理のために列挙してみる。

Service Name Price(tax included) Unit
日経Wプラン(宅配 + 電子版) 5,900円
Amazonプライム 3,900円
Github for Developer $84.00

もっとあるかと思ったけど、意外と少なかった。

「スタバなう」ツイートの画像は本当にスタバか、CNNで判定してみた

はじめに

Twitterで1日に一度くらいは「スタバなう」という投稿を目にする気がします。ただし大抵はキラキラ女子大生などを揶揄しており、ラーメンなどの画像とともに投稿されることが多いです。

f:id:upura:20180106131954p:plain

今回は、画像分類に秀でたConvolutional Neural Network (CNN)を用いて、「スタバなう」という語句を含むツイートの添付画像が本当にスタバの画像か否か判定してみようと思います。

データセットの構築

下記の記事でも触れたウェブサービスを用いて「スタバなう」という語句を含むツイートの添付画像を収集しました。

upura.hatenablog.com

手動でスタバの画像(正例)とそうでないもの(負例)に分類しました。枚数が中途半端なのは、ここで飽きたからです。

  • 正例:168枚
  • 負例:259枚

この段階で、検証用のデータセットとして以下の枚数分を取り出しました(当然、訓練用のデータセットとしては使いません)。

  • 正例:40枚
  • 負例:60枚

CNNの構築と学習

CNNの構築と学習には、下記の記事のPythonコードを再利用しました。もちろんパス名など細かい部分は修正しています(Github)。

upura.hatenablog.com

CNNの構造

f:id:upura:20171105180559p:plain

学習

327枚の訓練用のデータセットを学習させた結果は、下記の画像のようになりました。40ステップ辺りで収束していると分かります。
f:id:upura:20180107215708p:plain

分類結果

予想\正解
54 21
6 19

Precision = 0.72
Recall = 0.90
F-measure = 0.7999

指標についての説明はこちら。
F値 - 機械学習の「朱鷺の杜Wiki」

正と予想したのに正解は負だった画像(表の21)を調べてみると、スタバ以外のコーヒーチェーンの画像などが含まれていました。コーヒーカップは写っているのでロゴで判定するしかなく、これは間違えても仕方ないかなと思います。

おわりに

データセットの構築に飽きて訓練用のデータセットの枚数が少なくなった割には、高い性能を発揮できました。

もう少しデータセットを拡充してCNNのチューニングをすることで、さらに使い物になるレベルのアプリケーションにできそうです。顧客調査をしたいのにTwitterの画像検索が使い物になっておらずお困りのスターバックスマーケティング担当者さま、Githubでコードを公開しているので自由にお使いください。

github.com

【Twitter】特定キーワード&アカウントの画像を一括ダウンロードできるウェブサービス"timg"が便利

timg.azurewebsites.net

Twitterにおける特定キーワード&アカウントの画像を一括ダウンロードできるウェブサービス"timg"が大変便利だった。

例えば「スタバなう」を検索すると、以下のように直近ツイートから画像を表示してくれる(最大3200件)。右上から一括ダウンロードも可能。

f:id:upura:20180106131954p:plain

TwitterAPIを取得すれば、より自在にデータ収集できるが、サクッとデータを集めたい時には"timg"が適していると思う。

qiita.com

べき分布の対数を取る(ヒストグラムで可視化)

はじめに

べき分布の対数を取ると、ヒストグラムの形がどのように変わるか見てみた。やってみた後に気付いたが、数式的に当たり前の結果。

github.com

Jupyter Notebook

# 参考:https://qiita.com/tibigame/items/fa746573fbaf4666bc33
import numpy as np
import scipy
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set(style="whitegrid")
# 指数分布
# 平均して10分に1度起こる現象の発生間隔
rand_exp_scale = 10.0
rand_exp_size = 10000
rand_exp = np.random.exponential(scale=rand_exp_scale, size=rand_exp_size)

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plt.title('Histgram of np.random.exponential')
ax.set_ylabel('Frequency')
sns.distplot(rand_exp, kde=False, rug=False, bins=50)

f:id:upura:20180105090838p:plain

log_rand_exp = np.log(rand_exp )
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plt.title('Histgram of Log(np.random.exponential)')
ax.set_ylabel('Frequency')
sns.distplot(log_rand_exp, kde=False, rug=False, bins=50)

f:id:upura:20180105091600p:plain

pareto = np.random.pareto(a=2.718281828, size=10000)

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_ylabel('freq')
sns.distplot(pareto, kde=False, rug=False, bins=50)

f:id:upura:20180105091644p:plain

#  パレート分布
log_pareto = np.log(pareto)

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_ylabel('freq')
sns.distplot(log_pareto, kde=False, rug=False, bins=50)

f:id:upura:20180105091716p:plain

【遊戯王デュエルリンクス】竹光バーンに「所有者の刻印」を添えて デッキレシピあり

以下の効果を持つ「所有者の刻印」(通常魔法)を1枚加えることで、「エネミー・コントローラー」を食らった場合にも勝機が出現する。

フィールド上の全てのモンスターのコントロールは、元々の持ち主に戻る。

動き(例)


デッキレシピ(調整中)

f:id:upura:20180104080426j:plain

R:error "cannot remove prior installation of package ‘xxxx’"

Rでパッケージ(今回の場合は”MASS”)をインストールする際、下記のようなエラーが出た。

cannot remove prior installation of package ‘MASS’

エラーメッセージでググった結果「C:\Program Files\R\R-3.4.3\library」(パスはインストール設定やバージョンで異なる)の中の対象フォルダをエクスプローラーで削除してしまえば良いと分かった。RやRstudioが起動していると削除できないので、一度アプリケーションを落とす必要がある。

Error in installation a R package - Stack Overflow

その後、改めて下記コマンドでインストールする。

install.packages("MASS")