toshiのエンジニア日記

できるエンジニアを目指して勉強した内容を日々まとめていきます。

WindowsのAndroid StudioでKotlinを学ぶ - 導入編

こんにちは。 雑魚エンジニアToshiです。

先日Androidアプリをリリースしましたが、もっとちゃんと「Androidアプリ開発できます!」ってアピールするために、最近Android界隈で話題のKotlinを勉強してみることにしました。

本記事では、Windows上でのKotlinの導入手順などをまとめます。

なお、学習には日本Kotlinユーザグループが無料で公開してくださっている「Kotlin助走読本」を活用させていただく予定です。

kotlin-prior-learning-book.pdf - Google ドライブ

Android Studioのインストール

ここから、Windows用のAndroid Studioがインストールできます。

ダウンロードが完了すると、自動的にインストール手順を説明したページに遷移します。

説明にしたがって設定を行いましょう(まぁウィザードでぽちぽちするだけですが)。

Java環境の構築

Javaのインストールと設定をしましょう。

以下のTechAcademyの記事に従うと良いです。

Androidアプリの開発環境構築方法(Windows編)【初心者向け】 | TechAcademyマガジン

Kotlinプラグインのインストール

助走読本ではプラグインの導入に関して記述されていますが、Android Studio 3.0 以降のバージョンでは、最初からKotlinが導入されているようです。

新規プロジェクトの生成時に、ウィザード上で「Include Kotlin support」というチェックボックスにチェックをすればOKです。

Kotlinプロジェクトのつくり方などは以下の記事が参考になりました。

employment.en-japan.com

おわりに

以上で、KotlinでAndroidアプリ開発を行う環境構築ができました。

今後は、助走読本をベースにKotlinの勉強を進めていく予定です。

今年度中くらいに、Kotlin製のクソアプリをリリースしたいなぁ。

Androidアプリリリースしてみた

f:id:ntoshi1900:20180110212912p:plain

こんにちは。雑魚エンジニアのtoshiです。

約一ヶ月前に記事で書いてたスマホアプリですが、ついにリリースできました!

play.google.com

クリスマスを満喫するリア充どもを、様々な嫌がらせアイテムを投げつけて撃退するゲームです!

クリスマス当日にリリースしてましたが、そこから正月モードに入ってしまい、記事にするのをすっかり怠っていました;

15分くらいで全クリできるいい感じのクソゲーなので、お時間あれば遊んでみてください。

以下、リリース申請時の注意点などをまとめておきます。

Google Play Developer への登録

Androidアプリをリリースするためには、事前にGoogle Play Developer への登録が必要です。

以下のURLから登録申請が行えます。

https://play.google.com/apps/publish/signup/

登録には25ドルかかるので、事前にクレジットカード等を用意しておきましょう。

また、登録時にはポップアップが出てくるので、スマホからでは登録できません。PCから登録申請を行いましょう。

登録完了まで最大 48 時間かかるとのことですが、私はすぐに登録完了しました。

apkファイルの作成

Androidアプリをリリースする場合、もろもろのアプリ設定のほかに、Keystoreというデジタル署名用のファイルの生成が必要になります。

Unity上での生成の方法などは以下の記事が参考になります。

halcyonsystemblog.blog.fc2.com

Keystoreを紛失するとアプリのアップデート等ができなくなるそうなので、気をつけて管理しましょう。

ストアの掲載情報の入力

ストア上で表示されるもろもろの設定を行います。

f:id:ntoshi1900:20180110230613p:plain
アプリ一覧画面に表示される情報
f:id:ntoshi1900:20180110230607p:plain
アプリ詳細画面に表示される情報
f:id:ntoshi1900:20180110230602p:plain
アプリ詳細画面の下のほうに表示される情報

タイトル

アプリの顔、タイトルを入力します。

スマホでPlayストアを確認すると、アプリ一覧の画面ではタイトルの最初の全角20文字程度が見えるので、最初の20文字でゲームの内容が推測できるようにするといいかと思われます。

簡単な説明

かなり重要な項目です。

アプリをキーワードで検索したときに出てくるアプリ一覧画面では、タイトルとスクリーンショットのサムネイルと、この簡単な説明のみが表示されます。

基本的に、ここだけでアプリの魅力を伝えなければいけません。

最大全角80文字と限られた情報しか入力できないので、アプリの一番売りとなる内容を記述するようにしましょう。

ちなみに、改行を入れてしまうとアプリ一覧画面で1行目しか表示できなくなるようなので、1行で記述するようにするといいでしょう。

詳細な説明

実はあんまり優先度は高くないです。

というのも、スマホではアプリの詳細画面からさらに「詳細はこちら」というリンクをクリックしないと見えない部分だからです。

簡単な説明で記入したこと以外に伝えたいことがあれば記述すると良いと思います。

簡単な操作説明や、フリー素材のクレジット表記などを含めることが多いようです。

スクリーンショット

おそらく最も重要な項目になります。

アプリ一覧にも表示され、アプリの雰囲気をつかむために最も利用されるソースだと思います。 スクリーンショットで「面白そう!」と思わせれば勝ちです。

ゲーム画面に加えて、簡単な説明を付加した画像を生成するとわかりやすくていい感じです。

また細かいところになりますが、実際にゲームのプレイ中にいい感じのスクリーンショットを取るのは意外と難しかったりします。

スクリーンショット作成用の、敵とか弾とかが静止しているシーンを別途作成すると、楽でいい感じでした。

高解像度アイコン

タイトルと並ぶアプリの顔ですね。

アプリ自体に設定したアイコンと同じものを使うといいと思います。

ただ、512×512と、アイコンにしては本当に高解像度なので、Unity上でアイコンを設定する際も、512×512のアイコンをベースに作成するといいでしょう。

ヘッダー画像

これが意外と重要。

スマホでアプリの詳細画面を開いたときに、一番上にドーンと鎮座しています。 詳細を開いたときに一番最初に目にする部分なので、ここでインパクトを残せると大きいと思います。

プロモーション画像

これは良くわかりませんが、Google Play Store でオススメのアプリとして紹介されたときに表示される画像だそうです。

必須項目ではないですが、一応設定しておくとよいでしょう。

ちなみに私は面倒だったのでヘッダー画像を圧縮したやつを使いました。

プロモーション動画

Youtube上でのアプリ宣伝用の動画を載せられるみたいです。

本気でユーザ獲得を狙う場合は重要になるかもしれません。

ちなみに私はもちろん登録していません 笑

まとめ

Androidアプリのリリース作業は結構面倒くさい。

特に画像作成系が多いので、わりと時間とられます。

だけど、実際に自分の作品が世に出ることは、やっぱりうれしい!

できるだけ多くのプレイヤーにやってもらえるといいなーと願っております(まぁ紹介サイトに書くとかプロモーションなんもやってないので今回は厳しそうですが・・・)。

とりあえず一通りアプリ作成の手順はわかったので、今度はちゃんと面白いといえるゲームを作成していきたいです!

リモートもくもく会をやってみたらめっちゃ良かった

こんにちは、雑魚エンジニアのtoshiです。

最近、Unityを使ったスマホアプリ開発をはじめました!

もともとRPGツクールなんかを使ってちまちまとゲーム作りに励み、リアル友人たちにやってもらって喜んでいたのですが、どうせなら公開できるものを、と取り組み始めました。

ひとまず、評判のいい入門書として以下を購入、一通り実装してみました。

www.socym.co.jp

なにこれめっちゃ楽しい。NejikoRun超楽しい。

colliderなどの基礎をしっかり押さえた上でサンプルゲーム実装ができ、楽しく学べる良書でした。

さて、一通りサンプルアプリを作り終わったところで考えるのは、もちろんオリジナルゲーム!

……しかし、大きな壁が立ちはだかるのだった……!

やる気が出ない

設定を考え、ゲーム性を考え、さあ作るぞ!というとこまではいくのですが、いかんせんやる気が出ない。

のそのそと重い腰を上げ、コーディングを始めるのですが、クラスをひとつ作ったくらいで謎の達成感を覚え、気が付けばベッドで寝転びマンガを読んでいる。

いかん!これはいかん!いつまでたっても完成しない!!

そこで、開発をブーストするため、もくもく会というものを利用することにしました。

もくもく会とは?

f:id:ntoshi1900:20171127210420j:plain

もくもく会とは、共通の興味を持った人間がカフェやコラボレーティブスペースなどのひとつの場所に集まり、もくもくと作業をするという謎の会です。

決して、喫煙家が集まる不健康な会ではありません。

もくもく会のメリットとしては、

  • 人の目があるのでサボらない
  • 同じ興味の人が集まっているので分からないところがあったら質問できる
  • 成果発表を行うことで、目標感がある

などがあります。

とにかくサボってしまう私にとってはピッタリの会! ということで早速、Unity関連のもくもく会に参加してきました!

もくもく会参加の結果

結論から申し上げると、かなり作業は進みました

なにせサボれるベッドもないし、ちゃんと作業しないと「なんだあいつ」という冷たい視線が飛んでくる(という妄想)ので、サボることなく作業時間いっぱい開発ができました!

ただ。。。結構お金がかかる。

参加費自体は1000円程度で安かったのですが、東京までの交通費が結構かかる+外食で結構いいもの食べてしまう で、結果として6000円くらい吹っ飛んでいきました。

集中力は金で買えとも言うし、進み具合から言って損した気はしないのですが・・・頻繁に利用するにはちとお金が掛かりすぎる。

食費抑えろ?尤もな指摘ですが、難しい 笑

一日にかけたお金のうち、交通費が占める割合が高くなると、何か悔しくなっちゃうんですよね~ なので、せっかくだからといいものを食べ、結果お金がすっとんでいく・・・

そこで、何とかお金をかけずに開発をブーストできないかと考え、リモートもくもく会なるものを開催することにしました。

リモートもくもく会とは

f:id:ntoshi1900:20171127212949j:plain

もくもく会では物理的にひとつの場所に集まりますが、リモートもくもく会は音声通話やチャットアプリなどで、仮想的に集まります。

そのため、全員が自宅などで参加でき、交通費も移動時間もかけずに作業が開始できるというわけです。

取り合えずお試しということで、知り合いを4人ほど集め、Slack上で開催してみることにしました。

流れは以下のような感じです。

  1. 9:00 Slackにログイン。各自作業内容を宣言する。
  2. 9:00~12:30 各自作業。
  3. 12:30~13:00 各自休憩。お昼ごはんの内容と進捗状況を共有。
  4. 13:00~17:30 各自作業。
  5. 17:30~18:00 成果報告

仕事かっ!と突っ込みたくなるほどのガチ構成です(事前に参加者にアンケートとったらこのプランが一番人気だったんです・・・)笑

集中力が持つか心配でしたが、取り合えずものは試しということでこのプランでやってみることにしました。

その結果は・・・

めっちゃ良かった

すごい。すごい良かった。

まず「めんどくせ~」とかならずに、強制的に朝9時から作業が始められる。一番の壁である「やり始め」が超スムーズ。

さらに、報告会で報告する内容なくなったら困る、と思い、サボることもない。他の人にいい面するために必死こいてやる。

結果、めちゃくちゃ作業が進む!!しかも、無料!やばい!移動時間もなし!!何か無駄に豪勢な食事することもない!ステーキとか食べない!!

最高かよ・・・

ただし、いくつかリモートならではの問題点などもありました。

成果報告がちょっとグダグダ

成果報告もSlack上でチャットベースでやったのですが、成果報告のテンポが悪かったり、突然の来客でAFKしてなかなか戻ってこなかったりしました。

テンポに関しては、誰かが入力する → 待ってる間作業する → 作業しすぎて入力完了に気づくのが遅れる の連鎖で、かなりのグダグダ感。

チャットベースでリアルタイムで行うのは無謀でしたね・・・

あらかじめ入力して、各自読んでね!というスタイルにするか、成果報告だけでもSkype等で音声つなぐのが良さそうですね。

AFKに関しては、簡易でもいいので何か連絡してね、と取り決めるか、、、やっぱり音声つなぐのがいいですね。

個人的に作業中は音声つなぐ必要はないと思っているので、成果報告時のみ通話にするのが一番スマートにできる気がします。

作業内容が少し限定される節がある

今回、私はUnityのアプリ開発でしたが、他の方々は新しい分野を勉強をしている人もいました。

しかし、新規分野の勉強だと、「勉強しました!」くらいしかいうことがなく、成果報告時に報告する内容がほぼない、という状況に陥るようです。

デモシステムの構築くらいまで進めると成果として分かりやすいのですが、前準備なしに取り組むと基礎的な理論の理解だけで一日が終わってしまいます。

なので、成果報告でちゃんとモノを報告したい!となった場合には、新規分野をイチから学ぶのは少し厳しそうです。

あらかじめ基礎は理解して、実装部分をやる、等の工夫が必要そうです。

まあ、もくもく会なので、そこまで成果にこだわる必要はないとは思いますが・・・

まとめ

リモートもくもく会めっちゃ良い

この一言に限る。

ただし、成果報告は音声でやるのがオススメ。

あと新規分野やるときはある程度予習しとくのがオススメ。

以上!

とりあえずとてもとても素晴らしいので、

みなさんリモートもくもく会積極的にやりましょう

おまけ

リモートもくもく会で作ってたアプリを少し紹介します。

タイトル:Xmas Crusher ~リア充どものクリスマスを台無しにせよ!~

設定:寂しいクリボッチを味わう主人公。ついに我慢の限界を突破し、クリスマスを充実するリア充どもを殲滅するため、孤独な戦いに挑む!

f:id:ntoshi1900:20171128064021p:plain
タイトル画面。陰鬱な雰囲気が漂いますね・・・

f:id:ntoshi1900:20171128064937p:plain
戦闘画面。左右からワラワラとカップルが出てくるので様々なアイテムを投げつけて攻撃します

季節向けですが、完全なネタゲーです 笑

クリスマスまでに公開する予定なので、お楽しみに!

トランプ大統領と金正恩氏の類似度を潜在的意味解析で判定する その2

f:id:ntoshi1900:20171017202249p:plain 前回の記事では、wikipediaから各国の大統領の説明を取得しました。

今回は、このデータを使って潜在的意味解析を行い、トランプ大統領と金正恩氏の類似度を判定していきたいと思います。

以下の手順3からの再開です。

  1. wikipediaから各国の指導者一覧を取得
  2. 各国の指導者のwikipediaページから説明文を抽出
  3. 潜在的意味解析を用いて各指導者を潜在的空間に射影
  4. トランプ大統領と金正恩氏の類似度を判定する

3.潜在的意味解析で各指導者を潜在的空間に射影

まず、文書-単語行列を作成するために、RMeCabパッケージを使用できるようにします。

RMeCabのインストールは以下のページなどを参考にしてください。

RMeCab - RとLinuxと...

注意点としては、MeCabそのものもインストールを忘れないようにしてください。 RMeCabパッケージだけインストールして使用しようとすると、RStudioがエラー落ちしてしまいます。

さて、RMeCabが使えるようになったら、以下のコードで各指導者の文書-単語行列を作成します。

### 3. 潜在的意味解析を実行

# パッケージの読み込み
library("RMeCab")

## 各指導者の説明文から単語-文書行列を作成する

# 説明文が入ったファイルのあるディレクトリを指定
path.dir <- "./desc"

# 単語カウントの最低出現回数を指定
minF <- 2

# 単語-文書行列の作成(名詞と動詞と形容詞のみ使用)
# 重みとしてtf-idfを用い,正規化した値を出力する
docterm <- docMatrix(path.dir, minFreq=minF, 
                     pos = c("名詞", "形容詞"), weight = "tf*idf*norm")

# 先頭2行を削除
docterm.cut <- docterm[-(1:2),]
# minF個以上の文書にある語句のみピックアップ
docterm.select <- docterm.cut[which(apply(docterm.cut, 1, function(x) sum(x > 0) ) >= minF), ]

docMatrix関数でファイルの格納されたフォルダのパスを指定することで、文書-単語行列が生成されます。pos引数で使用する品詞を選択できるのですが、今回は名詞と形容詞のみを使用することとします。

また、weight引数で単語の重み付けのオプションを指定できます。今回はTF-IDFと正規化を指定しています。

TF-IDFは文書内での出現頻度と全体での出現頻度の割合を用いて、全体ではあまり出現しないが、特定の文書にだけ頻出する語句の重みを高くする手法です。これにより、文書をより特徴付ける単語の数値を大きくすることができます。

さて、得られた単語-文書行列の次元と、マトリクスの一部を確認してみましょう。

# 次元の確認
dim(docterm.select

# いくつか要素のの確認
print(docterm.select[1:10, 1:2])
> dim(docterm.select)
[1] 2341  273
> print(docterm.select[1:10, 1:2])
      docs
terms  アイスランド 首相 ビャルニ・ベネディクトソン.txt アイスランド 大統領 グズニ・ヨハンネソン.txt
  こと                                       0.06853151                                   0.03073494
  回復                                       0.18593731                                   0.00000000
  獲得                                       0.13186948                                   0.00000000
  議席                                       0.20001793                                   0.00000000
  月                                         0.09031433                                   0.01620163
  後                                         0.09847178                                   0.00000000
  首相                                       0.09794949                                   0.00000000
  進歩                                       0.36285404                                   0.00000000
  政権                                       0.08484629                                   0.00000000
  選挙                                       0.12390810                                   0.01852339

273個の文書に対し、2341種類の単語が存在していることがわかります。 また、各文書に対して単語が関連付けられていることが確認できます。「こと」や「月」などのどの文書にも含まれそうな単語が入っていますが、TF-IDFの効果もあり、重みは小さめになっていますね。

それでは、この文書-単語行列をSVDで低ランク近似しましょう。

## svdによる低ランク近似を実行
# 特異値の累積和が何割にいくまでを残すかのパラメータ
d.base <- 0.5

# svdを実行
svd.docterm <- svd(docterm.select)
# 低ランク近似
index <- which(cumsum(svd.docterm$d / sum(svd.docterm$d)) <= d.base)
svd.docterm.low <- NULL
svd.docterm.low$u <- svd.docterm$u[, index]
svd.docterm.low$v <- svd.docterm$v[, index]
svd.docterm.low$d <- svd.docterm$d[index]
rownames(svd.docterm.low$u) <- rownames(docterm.select)
rownames(svd.docterm.low$v) <- colnames(docterm.select)

SVDによる低ランク近似では、特異値の大きさが擬似的に潜在トピックの重要度を表すため、特異値の低いものは価値の低い潜在トピックとし、行列から取り除きます。 ここでは、どれくらいまで次元を落とすかという基準に、特異値の累積和が特異値全体の何割に到達するまでを残すかという基準を用います。

この値はハイパーパラメータになるため、本来は最適化すべき項目ですが、取り合えず0.5でやってみました。

では、低ランク近似後の行列の次元を確認してみましょう。

# 次元の確認
dim(svd.docterm.low$v)
> dim(svd.docterm.low$v)
[1] 273  82

2341次元あった単語ベクトルが、82次元まで削減できていますね。

では、この低ランク行列を保存して、余計な変数を削除しておきましょう。

# 低ランク行列の保存
save(svd.docterm.low, file="./svd_docterm_low.Rdata")

# 要らない変数を削除
rm(list=ls())
gc(); gc();

4.トランプ大統領と金正恩氏の類似度を判定する

ではついに!本題のトランプ大統領と金正恩氏の類似度を判定して見ましょう!

まずは、任意の2文書の全ての組み合わせでcosine類似度を計算します。

### 4. トランプ大統領と金正恩総書記の類似度を計算する

# 低ランク行列の読み込み
load("./svd_docterm_low.Rdata")

# cosine類似度の計算
mat.v <- t(svd.docterm.low$v)
matrix.cos <- apply(mat.v, 2, function(x){
  apply(mat.v, 2, function(y){
    crossprod(x, y) / (sqrt(crossprod(x) * crossprod(y)))
  })
})
diag(matrix.cos) <- NaN

これで、任意の組の類似度が得られるようになりました。

では、トランプ大統領と金正恩氏の類似度を出力してみましょう!

# トランプ大統領の番号を取得
index.trump <- which(rownames(svd.docterm.low$v) == "アメリカ合衆国 大統領 ドナルド・トランプ.txt")

# 金正恩総書記の番号を取得
index.kim <- which(rownames(svd.docterm.low$v) == "北朝鮮 朝鮮労働党委員長 金正恩.txt")

# トランプ大統領と金正恩総書記の類似度を出力
cat(matrix.cos[index.trump, index.kim])
> cat(matrix.cos[index.trump, index.kim])
0.05124007

んー、微妙ですね。

似ていない場合はマイナスの値をとるため、似ていないこともない、といったところでしょうか……

数値だけだとよくわからないので、トランプ類似度偏差値を求めてみます。

# トランプ大統領の類似度偏差値を計算
cos.trump <- matrix.cos[index.trump, ]
dev.trump <- (cos.trump - mean(cos.trump[-index.trump])) / sd(cos.trump[-index.trump]) * 10 + 50

# 金正恩総書記のトランプ偏差値を表示
print(dev.trump[index.kim])

# 金正恩総書記のトランプ順位の表示
trump.order <- dev.trump[order(-dev.trump)]
which(names(trump.order) == "北朝鮮 朝鮮労働党委員長 金正恩.txt")
> print(dev.trump[index.kim])
北朝鮮 朝鮮労働党委員長 金正恩.txt 
                          53.88065 
> which(names(trump.order) == "北朝鮮 朝鮮労働党委員長 金正恩.txt")
[1] 58

偏差値53.88……。とっても微妙ですね。

順位は273人中58位。悪くはないですが……期待したほどではない結果です。

では、トランプ大統領に最も似た指導者はいったい誰なのでしょうか?出力してみましょう。

# トランプ偏差値上位10人表示
print(trump.order[1:10])
> print(trump.order[1:10])
    フィリピン 大統領 ロドリゴ・ドゥテルテ.txt       パラグアイ 大統領 オラシオ・カルテス.txt 
                                     129.29781                                       94.31164 
                        韓国 大統領 文在寅.txt             ボツワナ 大統領 イアン・カーマ.txt 
                                      88.77724                                       84.07969 
      ベネズエラ 大統領 ニコラス・マドゥロ.txt キプロス 大統領 ニコス・アナスタシアディス.txt 
                                      77.19171                                       76.18902 
                バチカン 教皇 フランシスコ.txt                 日本 内閣総理大臣 安倍晋三.txt 
                                      73.40518                                       73.26178 
        ジンバブエ 大統領 ロバート・ムガベ.txt         カナダ 首相 ジャスティン・トルドー.txt 
                                      72.60202                                       71.23118 

なんと……類似度1位はフィリピンのドゥテルテ大統領で、なんとその偏差値129!!

大学受験とかで考えたらとんでもない化け物ですね!

そんなに似ているのか……とドゥテルテ大統領wikipediaページを見てみると、以下のような記述がありました。

選挙戦中は、同時期に進行していたアメリカ大統領選挙に立候補する共和党候補者を選出する予備選挙で過激な発言を行う人物として注目されていた共和党ドナルド・トランプになぞらえ、「フィリピンのトランプ」とも揶揄された。

まんま記述があるじゃないですか!

おそらく、この「トランプ」という単語とか、「大統領」という単語などが共通しているため、類似度が高くなったようですね。

それぞれの文書を特徴付ける上位10単語を確認してみましょう。

## 各指導者をもっとも特徴付ける単語を調べる

# 全指導者の文書-単語行列を低ランク行列で再現
docterm.app <- svd.docterm.low$u %*% diag(svd.docterm.low$d) %*% t(svd.docterm.low$v)

# トランプ大統領をもっとも特徴付ける単語を取得
term.trump <- docterm.app[,index.trump]

# トランプ偏差値トップの人をもっとも特徴付ける単語を取得
index.toptrumper <- which(rownames(svd.docterm.low$v) == names(trump.order)[1])
term.toptrumper <- docterm.app[,index.toptrumper]

# それぞれの特徴語の表示
print(term.trump[order(-term.trump)][1:10])
print(term.toptrumper[order(-term.toptrumper)][1:10])
> print(term.trump[order(-term.trump)][1:10])
  トランプ       中国     北朝鮮       こと       発言 フィリピン         者       米国     大統領         人 
0.34969567 0.20357833 0.17085699 0.13165502 0.12459490 0.10411936 0.10155474 0.09888835 0.09590375 0.09159767 
> print(term.toptrumper[order(-term.toptrumper)][1:10])
      中国   トランプ     大統領     北朝鮮         年 フィリピン       依存       発言       こと       政策 
0.18541337 0.15940956 0.11098858 0.08911449 0.07826024 0.07240096 0.06509865 0.06227812 0.06085533 0.05706989 

やはり、トランプ、大統領、といった単語が含まれていますね。

他には、中国、北朝鮮、といった単語が共通して出ており、体外的な交渉相手などが似ているということでしょうか。

まぁここに関しては、日本のwikipediaを解析しているため、日本から見た動きが記載されやすい、というバイアスは大きく受けている気はします。

実際に似ているかはともかく、日本から見た影響力の大きさ、という点では似ているのかもしれませんね。

おまけ:理想の指導者を探してみる

潜在的意味解析の面白いところは、文書の検索もできるところです。

任意の文書をクエリとして与え、そこに含まれる単語を潜在意味空間に射影することで、文書との距離を計算できるようになります。

では実際に、理想の指導者に最も類似する指導者を探してみましょう。

まずは、クエリを与えると、それに最も近い5つの文書を返す関数を定義しましょう。

## 理想の指導者を探してみる

# 理想の指導者検索関数の設定
searchLeader <- function(query, docterm){
  
  # 長さ1の文字列のみ受付
  if(mode(query) != "character") return(NULL)
  if(length(query) > 1) return(NULL)
  
  # 形態素解析
  query.term <- RMeCabC(query) %>% unlist()
  
  # 動詞,形容詞だけ取り出す
  query.term <- query.term[names(query.term) %in% c("名詞", "形容詞")]
  
  # 文書-単語行列に含まれるもののみを取り出し,ベクトルを生成
  term.list <- matrix(0, nrow=nrow(docterm$u))
  rownames(term.list) <- rownames(docterm$u)
  term.list[rownames(term.list) %in% query.term] <- 1
  
  # 使用される単語を確認
  cat("Using terms:\n")
  print(term.list[which(term.list[,1] == 1), ])
  
  # 文書-単語行列に全く一致する単語がない場合はNULLを返す
  if(sum(term.list) == 0) return(NULL)
  
  # 潜在意味空間中での質問文ベクトルを計算
  query.vec <- t(term.list) %*% docterm$u %*% solve(diag(docterm$d))
  query.vec <- as.vector(query.vec)
  
  # 潜在意味空間中でのcosine類似度を計算
  mat.v <- t(docterm$v)
  query.cos <- apply(mat.v, 2, function(x){
    crossprod(x, query.vec) / (sqrt(crossprod(x) * crossprod(query.vec)))
  })
  rank.leader <- round(sort(query.cos,de=T),3)
  
  return(rank.leader[1:5])
}

では、この関数を使用して、理想の指導者を探してみましょう。

以下のようなクエリを与えてみます。

# 指導者検索してみる
query <- "効果的な政策を実現することができ,経済の発展に貢献し,人々から賞賛され,尊敬を集める"

これが理想的な指導者かどうかは微妙ですが、すばらしい人物には違いないですね!

では検索してみましょう!

res <- searchLeader(query, svd.docterm.low)
print(res)
> res <- searchLeader(query, svd.docterm.low)
Using terms:
こと   的 経済 効果 貢献 実現 人々 政策 尊敬 発展 
   1    1    1    1    1    1    1    1    1    1 
> print(res)
  スリランカ 大統領 マイトリーパーラ・シリセーナ.txt     ジョージア 首相 ギオルギ・クヴィリカシヴィリ.txt 
                                               0.477                                                0.427 
ジョージア 大統領 ギオルギ・マルグヴェラシヴィリ.txt             インドネシア 大統領 ジョコ・ウィドド.txt 
                                               0.377                                                0.372 
    コスタリカ 大統領 ルイス・ギジェルモ・ソリス.txt 
                                               0.328 

スリランカの大統領が一番該当すると出てきました。

ちょっとどんな人物か良くわからないので、wikipediaページを見てみましょう。

マイトリーパーラ・シリセーナ - Wikipedia

んー、特別クエリに該当しているようには思えないんですが……

取り合えず文章が短めなので、出現する単語の種類が少なくなり、「政策」とか単語の重みが強くなったんでしょうか。

試しにほかのクエリでもやって見ます。

query <- "親日で日本が大好きで友好的"
res <- searchLeader(query, svd.docterm.low)
print(res)
> res <- searchLeader(query, svd.docterm.low)
Using terms:
  的 日本 友好 
   1    1    1 
> print(res)
    シンガポール 首相 リー・シェンロン.txt     パラオ 大統領 トミー・レメンゲサウ.txt 
                                     0.914                                      0.475 
モルディブ 大統領 アブドゥラ・ヤミーン.txt             日本 内閣総理大臣 安倍晋三.txt 
                                     0.457                                      0.320 
        ツバル 総督 イアコバ・イタレリ.txt 
                                     0.190 

最も親日な指導者はシンガポールの首相でした。

リーシェンロン首相はこんな人です。

リー・シェンロン - Wikipedia

うーん、また文章が短く、日本に関する記述が目立ちますね。

どうも、検索のような短いクエリと距離を計算すると、文書が短く、たまたまクエリに近い単語を含んでいる文書が上位に上がってきてしまうようです。

今回のような各文書に含まれる単語数が大きく違う場合は、一工夫必要そうです。

まとめ

今回は潜在的意味解析を用いて、トランプ大統領と金正日氏の類似度を判定してみました。

その結果、実はトランプ大統領が似ているのは金正日氏ではなく、ダントツでフィリピンのドゥテルテ大統領であることがわかりました(飽くまで今回の解析の結果です)。

今回は日本のwikipediaの文書を解析したため、日本の視点から見た行動、というバイアスのかかった結果になってしまいましたが、例えばTwitter上での指導者に対する意見を分析するなどすれば、世間からどう思われているかという点での類似度が計算できるかもしれません。

ちなみに潜在的意味解析の改良法で確率的潜在意味解析(PLSA)という手法もあるので、時間があれば勉強してみたいですね。

トランプ大統領と金正恩氏の類似度を潜在的意味解析で判定する その1

f:id:ntoshi1900:20171016212430j:plain

こんにちは、雑魚エンジニアのtoshiです。

最近、トランプ大統領と金正恩氏が似ていると、ネット上で言われるようになってきました。 その証拠に、Google検索で「トランプ 金正日」と入力すると、サジェストに「似てる」という単語が上位に出てきます。

お互い過激な発言が目立ちますから、仕方ないかなぁ、といったところですね。

さて、今回はそんな二人が本当に似ているのかどうか、潜在的意味解析という技術を使って解析してみたいと思います。

潜在的意味解析とは

潜在的意味解析(LSA)とは、文書に存在する単語を用いて、潜在的なトピックを抽出する技法です。

具体的に言うと、文書に存在する単語を出現回数を数え上げたベクトルに変換(Bag of Words)し、SVDによる低ランク近似を行います。

そうすることで、類義語のような、同じような使われ方をする単語が潜在的なトピックとして畳み込まれます。

そのため、単純に文書-単語行列によって類似度を判定するのと比べ、より柔軟に類似度判定を行うことができます。

潜在的意味解析の詳細な説明は省きますが、もう少しわかりやすく知りたければ、以下のあらびきさんのエントリが分かりやすいです(潜在的意味インデキシング(LSI)と書かれていますが、潜在的意味解析と同じです)。

abicky.net

作業環境と手順

以下の環境で作業を行います。

  • OS  : Windows7
  • 言語 : R言語 (バージョン3.4.2)
  • IDE  : Rstudio (バージョン1.1.383)

以下のような手順で解析を行っていきます

  1. wikipediaから各国の指導者一覧を取得
  2. 各国の指導者のwikipediaページから説明文を抽出
  3. 潜在的意味解析を用いて各指導者を潜在的空間に射影
  4. トランプ大統領と金正恩氏の類似度を判定する

では、早速やっていきましょう!

1.wikipediaから各国の指導者一覧を取得

Webスクレイピングを行うには、rvestというパッケージが利用できます。 CRANからインストールできますので、しておきましょう。

install.package("rvest")

ちなみにDBpediaからSPARQLでデータ引っ張ってくることも考えたのですが、DBpedia上の各国の指導者一覧ページが最新でなかったため、wikipediaからスクレイピングすることにしました。

さて、各国の指導者一覧のHTMLを読み込むコードを以下に示します。

### 0. 準備
# カレントディレクトリの設定
setwd("~/R_workspace/LSA")

# パッケージの読み込み
library("rvest")

### 1. wikipediaから各国の指導者一覧を取得
# 各国の指導者一覧HTMLの取得
url <- "https://ja.wikipedia.org/wiki/%E4%B8%96%E7%95%8C%E5%90%84%E5%9B%BD%E3%81%AE%E6%8C%87%E5%B0%8E%E8%80%85%E4%B8%80%E8%A6%A7"
data.html <- read_html(url)

# 指導者テーブルの取得
html.table <- data.html %>% html_nodes(xpath="//table") %>% .[1] %>% 
  iconv(from = "UTF-8", to="UTF-8")

read_html関数でHTMLを読み込んだ後、html_nodes関数でタグを指定してやることで、そのタグを持つHTMLコードだけを取得できます。 今回はtableタグを指定しているので、テーブルだけが取得できています。

目的のテーブルは1番目のテーブルなので、1番目の要素を取り出し、iconv関数で文字化けを解消しておきます。 iconv関数は文字コードを変換するためのものですが、これをしておかないととんでもなく文字化けするので、重要です。

さて、本来であればここからhtml_tableという関数を用いることでテーブルの各セルの要素を取り出すことができるのですが、

  • html_table関数では結合セルをうまく扱えない
  • html_table関数では要素だけをdata.frameに変換するためハイパーリンクが取り出せない

ことから、自力でHTMLコードを解析していきたいと思います。

少し煩雑になりますが、以下がテーブルのHTMLから各要素を取り出すコードです。

# trタグで分割して、各行のデータを取り出す
html.leaders <- html.table %>% strsplit("<tr>") %>% .[[1]]

# 各指導者ごとにデータを作成
len <- length(html.leaders)
table.leader <- data.frame("国名"=rep(NA, len - 2), 
                           "役職"=rep(NA, len - 2), 
                           "名前"=rep(NA, len - 2), 
                           "URL"=rep(NA, len - 2))

# HTMLを自力で分解する
# 1,2行目はヘッダなのでスルー
for(index.loop in 3:len){
  # tdタグで分割
  td.vec <- html.leaders[index.loop] %>% strsplit("<td") %>% .[[1]]
  # td.vec[1]から国名を取得
  # 結合セルの関係で既に埋められている場合スルー
  if(is.na(table.leader[index.loop - 2, "国名"])){
    # 結合セルだった場合,先のデータも埋めるため変数にrowspanを代入
    if(length(grep("rowspan", td.vec[1])) > 0){
      rowspan <- td.vec[1] %>% strsplit("rowspan=\"") %>% .[[1]] %>% 
        .[2] %>% strsplit("\"") %>% .[[1]] %>% .[1] %>% as.numeric()
    } else {
      rowspan <- 1
    }
    # タグの後ろにある要素を取り出す
    td.split <- td.vec[1] %>% strsplit(">") %>% .[[1]]
    for(sub.loop in 1:length(td.split)){
      # 国名はaタグの終わり前にあるため,</で分割できた0文字以上の要素を取出
      temp.data <- td.split[sub.loop] %>% strsplit("</") %>% .[[1]]
      if(length(temp.data) > 1 & nchar(temp.data[1]) > 1){
        # 結合セルの場合、複数セル分の国名を代入する
        start <- index.loop - 2
        end <- start + rowspan - 1
        table.leader[start:end , "国名"] <- temp.data[1]
        break
      }
    }
  }
  # td.vec[2]から役職を取得
  # 結合セルの関係で既に埋められている場合スルー
  if(is.na(table.leader[index.loop - 2, "役職"])){
    # 結合セルだった場合,先のデータも埋めるため変数にrowspanを代入
    if(length(grep("rowspan", td.vec[2])) > 0){
      rowspan <- td.vec[2] %>% strsplit("rowspan=\"") %>% .[[1]] %>% 
        .[2] %>% strsplit("\"") %>% .[[1]] %>% .[1] %>% as.numeric()
    } else {
      rowspan <- 1
    }
    # タグの後ろにある要素を取り出す
    td.split <- td.vec[2] %>% strsplit(">") %>% .[[1]]
    for(sub.loop in 1:length(td.split)){
      # 役職名もaタグの終わり前にあるため,</で分割できた0文字以上の要素を取出
      temp.data <- td.split[sub.loop] %>% strsplit("</") %>% .[[1]]
      if(length(temp.data) > 1 & nchar(temp.data[1]) > 0){
        # 結合セルの場合、複数セル分の役職名を代入する
        start <- index.loop - 2
        end <- start + rowspan - 1
        table.leader[start:end, "役職"] <- temp.data[1]
        break
      }
    }
    # 名前が入っているデータのインデックスを設定
    name.index <- 3
  } else {
    # 役職が結合セルの場合,名前が入っているインデックスがずれるので補正
    name.index <- 2
  }
  # 名前とURLを取得
  # タグの後ろにある要素を取り出す
  td.split <- td.vec[name.index] %>% strsplit(">") %>% .[[1]]
  for(sub.loop in 1:length(td.split)){
    # リンクが存在する要素にリンクと名前が入っているため、href="で分割
    temp.data <- td.split[sub.loop] %>% strsplit("href=\"") %>% .[[1]]
    if(length(temp.data) > 1){
      # URLと名前をそれぞれ取り出して記録
      temp.data <- temp.data[2] %>% strsplit("\"") %>% .[[1]]
      table.leader[index.loop - 2, "URL"] <- 
        paste0("https://ja.wikipedia.org", temp.data[1])
      table.leader[index.loop - 2, "名前"] <- 
        td.split[sub.loop + 1] %>% strsplit("</") %>% .[[1]] %>% .[1]
      break
    }
  }
}

# 一人の人物が複数の役職を兼任している場合,2つ目の役職の名前とURLにNAが入っているので削除
table.leader <- na.omit(table.leader)

だいぶ愚直に書きましたが、いちおうこれでテーブルのHTMLから各国の指導者情報を取り出すことができます。 HTMLの構造が変わると対応できない等、結構クソコードな気はしますが……

まぁ、スクレイピング部分は今回のお題の本質的な部分ではないので良しとしましょう(^_^;)

さて、中身を確認してみましょう。

# ちゃんと取れているか確認
View(table.leader)

f:id:ntoshi1900:20171016230220p:plain

どうやらちゃんと取れてそうですね。

では、このデータを保存して、余分な変数を削除しておきましょう。

# table.leaderの保存
save(table.leader, file="./table_leader.Rdata")

# 要らない変数を削除
rm(list=ls())
gc(); gc();

2.各国の指導者の各ページから説明文を抽出

各国の指導者の説明文も、rvestパッケージで取得することができます。

前回はテーブルの読み込みだったため html_nodes関数においてtableタグを指定しましたが、今回はpタグを指定して読み込みましょう。

以下に、それぞれの説明文を取得するコードを示します。

### 2. 各指導者のWikipediaページから説明文を取得し保存する
# table.leaderの読み込み
load("./table_leader.Rdata")

# 説明文の保存先作成
path.dir <- "./desc"
if(!file.exists(path.dir)) dir.create(path.dir)

# 全指導者の説明文を取得し保存
for(index.loop in 1:nrow(table.leader)){
  
  # URL設定
  url <- table.leader[index.loop,4]
  
  # タイムアウトの回数を記録する変数の作成
  timeout.count <- 0
  
  # データの取得
  while(TRUE){
    data.html <- try(read_html(url), silent = FALSE)
    # データが取得できた場合と,404エラーの場合は次の処理へ
    if(class(data.html)[1] != "try-error"){
      break
    } else if(length(grep("error 404", data.html[1])) > 0){
      break
    }
    # タイムアウト等のエラーの場合は5秒まってリトライ
    Sys.sleep(5)
    
    # タイムアウトの回数を記録し、10回連続失敗したら諦める
    timeout.count <- timeout.count + 1
    if(timeout.count >= 10) break
  }
  
  # 記事が存在しない場合はスルー
  if (class(data.html)[1] != "try-error" & timeout.count < 10) {
    # 本文の取得
    sentence.main <- data.html %>% html_nodes(xpath="//p") %>% 
      iconv(from = "UTF-8", to="UTF-8")
    
    # 全文の結合
    sentence.main.all <- paste(sentence.main, collapse = "")
    
    # タグと参考文献の削除
    sentence.main.notag <- gsub("\\[.*?]", "", 
                                gsub("<.*?>", "", sentence.main.all))
    
    # 括弧書きの削除
    sentence.main.notag <- gsub("(.*?)", "", 
                                gsub("\\(.*?)", "", sentence.main.notag))
    
    # 説明文を保存
    filename <- paste0(path.dir, "/", 
                       paste(table.leader[index.loop,1:3], collapse=" "), ".txt")
    write(sentence.main.notag, filename)
    
  }
  
  cat("finish : ", index.loop, "/", nrow(table.leader), "\n")
}

# 要らない変数を削除
rm(list=ls())
gc(); gc();

後にRMeCabを用いて文書-単語行列に変換するために、それぞれの説明文を「国名 役職名 人名」のファイル名で保存しています。

さて、ちゃんと取れているか、保存したテキストファイルを確認してみましょう。

f:id:ntoshi1900:20171016234227p:plain

長いですが、取れてそうですね。

続きは次回の記事で

まだ下準備しかできていませんが、だいぶ長くなってしまったので、続きは次回記事で紹介したいと思います。

果たしてトランプ大統領と金正恩氏は似ているのか!?

乞うご期待です!

次回記事はこちら

CEATEC 2017 に行ってきた

f:id:ntoshi1900:20171006214844p:plain

毎度おなじみ、IT技術とエレクトロニクスの国際展示会のCEATECに行ってきました!

個人的に気になったやつを紹介していきます!

CASIOさんの2.5次元プリンター Mofrel

f:id:ntoshi1900:20171006214922j:plain

これは一目見てすごい!といえる機器でした。

2.5次元という名の通り、表面形状を自由に変化させ、凹凸を表現できるプリンターです。

これの凄いところが、3Dプリンターのように物質を積層するのでなく、紙そのものを膨張させて立体を表現しているところです。

そのため、3Dプリンターのように多大な時間をかけることなく、3~6分程度で立体を表現できてしまいます。

それだけスピーディにも関わらず、精巧さはかなりのものでした。

f:id:ntoshi1900:20171006214944j:plain
立体的に印刷されたカメレオン。一瞬本物かと見紛うほどのクオリティ

ただ、弱点として

  • 凹凸の表現が1.8mmまでが限界
  • 専用紙が1枚1000円ほどと高額

などがあるそうです。

今は製品プロトタイプの作成などで使ってほしいとのことでしたが、コストもかかりますし、どういう分野に活用していけるかを考えるのが今後の課題になりそうですね。

残念ながらコンシューマ向けに出てくることは当分ないでしょう。

これで年賀状作ってみたかったな(´・ω・`)

ASUKANETさんの空中ディスプレイ

f:id:ntoshi1900:20171006221952j:plain

これも、かなりインパクトのある製品でした。

表示している画面が、空中に浮き出て見えるディスプレイです。

そこにあるのに触れない、という不思議な感覚を味わうことができます。

実に未来感のある製品ですね!

f:id:ntoshi1900:20171006221959j:plain
サイネージの例。写真だと微妙ですが、リアルに見るといい感じに飛び出して見えます

視野角は結構限定されていて、特定の位置に立たないと立体には見えづらいです。

逆にそれを利用して、ATMの操作インターフェースに使おうという考えもあるみたいですね。

ちなみに、逆側の展示できれいなお姉さんが飛び出る展示をやっていましたが、超絶混雑で見れませんでした……

Twitterとかでかなり話題になっていましたね。

2次嫁と生活できる日も、そう遠くはないかも?笑

4年連続!オムロンさんの卓球ロボ フォルフェウス

f:id:ntoshi1900:20171006215417j:plain
おなじみのアイツ。今年も体験ができました

CEATEC参加者にはおなじみですね。4年連続の出展のフォルフェウスさんです。

今年はサーブ機能とスマッシュ機能が搭載されたらしいです。

サーブはちゃんとトス→打球でできていて凄かったです。ボールのトスまで時間がかかるのがネックですが……

スマッシュは見れなかったですね。

ちなみに私も体験してみましたが、どこに打っても大体返してくれるので凄いです。ロングは少し苦手なようですが。

ただ、ラケットのラバーがツルツルのカスカスですごいやりづらい……打っても全然飛びません

がんばってループドライブ打ってみたところ、普通にオーバーしていたので、まだ回転には対応できてないみたいですね。

来年にはどこが進化するのか楽しみです。

話題のブロックチェーンMUFGさんのMUFGコイン

f:id:ntoshi1900:20171006215015j:plain
説明板の横に自販機で水が買えるデモが展示されていました。

満を持しての登場ですね。かなり前から話題になっていました。

MUFGコインは1コイン=1円と固定された価値をもつコインなので、実質電子マネーみたいなものですね。ビットコインみたいな投機には使われません。

電子マネーとの違いは、個人間でコインのやりとりができるところで、例えば割り勘のときに皆からコインを集めたりできます。

送金手数料もかからないので、かなり取り回しは良さそうですね。

ではどうやって儲けるのか、というと、このコインでの収益は一切期待していないそうです。

MUFGがこのコインを出した理由としては、ブロックチェーン技術に対する危機感。

ブロックチェーン技術が、もしかしたら銀行の存在価値を奪ってしまうかもしれない。

そんな破壊的イノベーションが起こったときに、生きる術としてブロックチェーンに乗り換えられるように今のうち技術を作っておく、というアプローチのようですね。

対応サービスが増えればなかなか使えるようになると思います。

流行のチャットボット

WatsonサミットやビッグデータEXPOなんかでもそうでしたが、相変わらず流行ってますねチャットボット。

CEATECでは会話できるロボットやARのキャラクターなどが多数展示されていました。

Watson先生万歳かと思いきや、意外と内製のエンジン使ってるとこも多かったです。

Nextremerさんの浅草観光案内ロボ AI-SAMURAI

f:id:ntoshi1900:20171006215009j:plain
無骨な鎧姿に、顔だけめっちゃサイバー。ちょっと怖い

浅草の観光情報を学習したチャットボットを搭載した観光案内ロボ。

内製のエンジンを使用しておりDeepLearningは使ってないらしいですが、精度は良かったです。

浅草のオススメのお土産を聞いてみたら芋ようかんをおすすめされました 笑

豆蔵さんのチャットボットエンジン

f:id:ntoshi1900:20171006225652j:plain
ロボ自体に特別な意味があるわけではなく、しょぼいハードウェアでも動きますよというデモ

とにかく軽量で、スタンドアロンでも動きます、ということを売りにしたチャットボットエンジン。

簡単に辞書も追加できて、クラウドに接続しなくてもいいです、という非常に取り回しの利く感じはよさそうだった。

ラズパイでも動くというのがすごい。

Panasonicさんの幼児向けソーシャルロボット cocotto

f:id:ntoshi1900:20171006215052j:plain
凄いスムーズにぐるぐる動き回ります。移動の機構がすごい

ものすごく軽快に動き、ひときわ目を引いていたロボット。

この笑顔といい、とってもかわいらしいですね。一人暮らしの寂しさを紛らわすにはいいかも?笑

動きのデモだけだったので、会話性能は不明。

バンダイナムコさんのガンシェルジュ ハロ

f:id:ntoshi1900:20171006215000j:plain
めっちゃコアなガンダムのクイズ出してきます。まったく分からん

これはいろいろと話題でしたね。

私はあんまりガンダム詳しくないですが、再現度は高いのではないでしょうか。

会話内容がめっちゃガンダムなので、ガンダム好きにはたまらない一品だと思います。

KDDIさんのヨリソイ型ハーフヒューマノイド レナ

f:id:ntoshi1900:20171006215100j:plain
三太郎って言ったらちゃんと反応してくれました

5Gの説明をしてくれるARキャラクターです(かわいい)

LTEの説明ができないなど、中身は結構へっぽこでしたが…… 笑

詳しく聞いてみると、他社製のエンジンをつかっているらしく、適当なことを言うと取り合えずなんか返事しちゃうあたりDeepLearningっぽい挙動でした。

まとめ

やはりCEATECは未来感を感じさせてくれる楽しいイベントです。

今回もいろいろとワクワクさせられました。

空中ディスプレイなんかは特に、サイネージのあり方を大きく変えそうです。

今回は紹介しませんでしたが、VRの展示もかなり流行っていて、いろいろなコンテンツが紹介されていました。

エンターテインメント分野での発展も、今後楽しみですね。

Amazon Echoを買う前に考えたい3つのリスク

f:id:ntoshi1900:20171003224128p:plain

こんにちは。 雑魚エンジニアのtoshiです。

遂に、Amazon Echoの日本での発売が発表されましたね!

news.yahoo.co.jp

米国でも品切れ状態が続いているらしく、大注目の商品です。

個人的にも、こういう未来感のあるデバイスはワクワクします。

さて、いろいろと期待が膨らむAmazon Echoですが、実は米国ではいろいろな問題が発生しています。

今回は日本に上陸する前に、Amazon Echoのリスクに関してまとめてみたいと思います。

リスク1:テレビの声に反応して誤動作する

Amazon Echoには個人認証機能がありません。

それゆえ、所有者本人でなくても、テレビの登場人物であっても操作が可能なのです。

実際の事例として、アニメの声に反応して誤動作した事例がありました。

www.dream-seed.com

これは、米国の国民的アニメ“サウスパーク”の一場面で、アニメ中のキャラクターがAmazon Echoへ命令した結果、実際にTVの前に設置したAmazon Echoが反応してしまった事例です。

今回はカートに変なものが追加される程度でしたが、その気になればアニメDVDを大量に購入させることもできるかもしれません。

対策としては、Amazon Echoは設定を変更することで起動ワードを変えたり注文時にパスワードを求めるようにしたりできるそうです。

可用性と機密性のバランスをしっかりと考えて、初期設定を万全に行いたいですね。

リスク2:子供に操作されてしまう

問題点1とも関連しますが、使い方さえ覚えてしまえば子供でもAmazon Echoに命令を出すことができます。

実際の事例として、アメリカの6歳の女の子が親に内緒で160ドル分のドールハウスとクッキーを注文してしまったという事例があります。

www.lonestar.jp

最近は子供が親のスマホのロックを突破して、勝手に使ってしまうといった話も聞きますよね。

それと同じように、たとえAmazon Echoにパスワードを設定したところで、子供は親の注文のときのセリフを覚えてAmazon Echoのロックを突破してしまうかもしれません。

注意しておかないと、親は知らぬうちに子供に大量のプレゼントをしてしまうハメになってしまうかも……

また、そのニュースをテレビで放映したところ、視聴者のAmazon Echoがそれにまた反応してドールハウスを注文しようとしたという笑えない話もあります。

まさに問題点1が発現した事例ですね。

news.livedoor.com

これは実際に注文までいってしまった人もいるらしく、番組に相当数の苦情が入ったとか。

対策としては、Amazon Echoは声による注文をオフにすることができるようなので、安全性を考えると注文はできない設定にするのが良いかもしれません。

自分もまったく注文できなくなるのは残念ですが……

リスク3:DolphinAttackにより攻撃される

音声認識のデバイスを攻撃する手段としてDolphinAttack(ドルフィンアタック)と呼ばれるものがあります。

【ドルフィンアタック】スマートスピーカーはハッキング可能!? 「人間に聞こえない音声で操作可能」との論文が発表 | ロボスタ

これは、人間には聞こえない音声で音声認識バイスを攻撃する方法で、持ち主に気づかれずに任意の命令を実行させることが可能です。

DolphinAttackに関して書かれた論文では、iPhoneのSiriやAmazon Echoなど、16種類のハードウェア、7種類のAI音声アシスタントで操作できることが報告されています。

iPhoneなどは基本的に常に携帯するのものなので、もしDolphinAttackをかけられても音声の返答があるため異変に気付くことは容易です。

しかし家に常備するAmazon Echoは留守中など、そばを離れていると時に操作されると気付くことができません。

使わないときは必ず電源をオフにしておくなど、厳密な管理が必要となるかもしれませんね。

まとめ

Amazon Echoのリスクを3つ紹介しました。

どれも金銭的な実害を及ぼす可能性があり、危険性は小さくありません。

しかし、Amazon Echo自体はすばらしい製品だと思いますし、人々の生活を変えていく可能性にワクワクしています。

ユーザみんながリスクをちゃんと把握して、正しい設定と正しい運用方法で対策をしていくことが重要ですね。

日本での発売日が楽しみです!