u++の備忘録

Google Homeで「室内留学」のすゝめ

はじめに

今更ながら、下記の記事を見て無性にGoogle Homeが欲しくなったので、昨日に購入しました。

note.mu

f:id:upura:20180117091042j:plain

用途:「室内留学」

僕の場合の用途は、自宅(※独り暮らし)で英会話ができる「室内留学」環境の構築です。

Google Homeを利用する利点は、以下のようなものが挙げられます。

音声操作のため、半強制的かつ手軽に英語を話す/聞く環境下を構築できる

  • 例えば目覚まし時計のアラームを止めるためにも、英語を話す必要が生じます
  • 朝には身支度をしながら「Tell me 'MyDay'」と言うだけで、今日の天気・最新のニュースを英語で流してくれます
    • "How can I get to the office"と聞くと、何時の電車に乗れそうかを教えてくれます
  • 何か調べたいときにも、わざわざスマホやPCを立ち上げることなく音声で処理しようとして英語を発するようになります

英会話教室や実際の留学と違って相手が「忖度」してくれない

  • Google Homeさんは発音が悪いと全く相手にしてくれません
  • 向こうから助け舟を出してくれることも、ほとんどありません
    • 目的語が足りないなど一定の条件下で聞き返してくれることも
  • 一方で生身の人間と違い、何回も話しかけても嫌な顔をしないという利点もあります

取りあえず一日稼働させただけですが、結構な量の英語を話す/聞くことができたので、今後も続けていきたいと思っています。

Google Home」か「Google Home Mini」か

店頭で店員に確認したところ

機能的に「できること」の違いはない

マイクとスピーカーの性能が違う

  • Miniはマイクが1個で、通常版は2個。通常版は高さがある分、聞き取る可能性が高くなる
  • スピーカーとしての音質/音域が違う

とのことでした。

スピーカーについては想定用途にも依りますが、店頭で確認すべきかと思います。個人的には結構違いました。

今回の用途はGoogle Homeとのやり取りが大切になるため、コミュニケーションの障害になりうる要素は極力排除したいと思い、倍の値段にはなりますが通常版を選択しました。

諸設定(参考までに)

  1. Google Homeのデフォルト初期設定
    • マニュアルに沿って設定します。この初期設定の終了時点では言語設定が日本語になっています。もちろん英語で話しかけても理解してくれません。
  2. 言語設定の変更
  3. ニュースの設定
    • スマホGoogle Homeアプリから、英語のニュースを追加し、(必要に応じて日本語のニュースを外し)流す順番を整備します
  4. 音楽の設定

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サービス一覧 (Aug, 2018)

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

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

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

「スタバなう」ツイートの画像は本当にスタバか、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