About Turi Create

Turi Createって何?

https://github.com/apple/turicreate

Appleが先日公開した機械学習のライブラリです。
READMEをみると…

1
2
You don't have to be a machine learning expert to add recommendations,
object detection, image classification, image similarity or activity classification to your app.

機械学習のエキスパートでなくても、リコメンドシステムなどが作れる…ほう(・ω・)
僕は、エキスパートではないので、僕でも本当に作れるか試してみます(`・ω・´)

ということで、この2つを作ってみます!

  • Recommender systems(リコメンド)
  • Image classification(画像分類)

導入

まずはじめにTuri Createをインストールします。
以下のようにすると、入れることができます。
※Python 2.7, 3.5, 3.6推奨

1
pip install -U turicreate

映画のリコメンド

最初は、映画のリコメンドシステムです(`・ω・´)
ユーザーさんが見た映画の履歴を元に、
次、この映画を見たほうがいいよと教えてくれるリコメンドシステムを作ります。

訓練データ

訓練データには、こちらのCSV形式(190MB)のデータを使います。
https://grouplens.org/datasets/movielens/

data

CSVのデータの中身は、こんな感じです。

data

CSVの読み込み

先ほどのCSVデータを読み込みます。

1
2
3
import turicreate as tc
data = tc.SFrame.read_csv('data.csv')
data.explore()

読み込みますと、こんな感じに表示されます。
ちなみに、この表示機能はTuri Createに標準でついている機能です。

read-csv

SFrameって何?

先ほどのコードにSFrameという見慣れないものがあると思います。

https://github.com/turi-code/SFrame

こちらは、データ分析用に作られたスケーラブルなデータ構造らしいです。
また、SQLのフィルタ, ソート, ジョインなどのようなことができます!

学習

先ほどのデータを使って、学習させます。

1
2
3
4
training_data, validation_data
= tc.recommender.util.random_split_by_user(data, 'userId', 'movieId')
model
= tc.recommender.create(training_data, 'userId', 'movieId')

結果は、こんな感じになり、無事に学習ができました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Recsys training: model = item_similarity
Warning: Ignoring columns rating, timestamp;
To use one of these as a target column, set target = <column_name>
and use a method that allows the use of a target.
Preparing data set.
Data has 80004 observations with 671 users and 8393 items.
Data prepared in: 0.06855s
Training model from provided data.
Gathering per-item and per-user statistics.
+--------------------------------+------------+
| Elapsed Time (Item Statistics) | % Complete |
+--------------------------------+------------+
| 14.361ms | 100 |
+--------------------------------+------------+
Setting up lookup tables.
Processing data in one pass using dense lookup tables.
+-------------------------------------+------------------+-----------------+
| Elapsed Time (Constructing Lookups) | Total % Complete | Items Processed |
+-------------------------------------+------------------+-----------------+
| 228.774ms | 0 | 0 |
| 547.001ms | 100 | 8393 |
+-------------------------------------+------------------+-----------------+
Finalizing lookup tables.
Generating candidate set for working with new users.
Finished training in 1.56964s

検証

先ほどの学習したものの検証を行います。

1
2
3
res = model.evaluate(validation_data)
pro = res['precision_recall_overall']
pro.print_rows(18,3)

結果は、こんな感じです(`・ω・´)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+--------+-----------------+------------------+
| cutoff | precision | recall |
+--------+-----------------+------------------+
| 1 | 0.0746268656716 | 0.00222957408534 |
| 2 | 0.0910447761194 | 0.00849339445401 |
| 3 | 0.0980099502488 | 0.0140232349614 |
| 4 | 0.10223880597 | 0.0197251532314 |
| 5 | 0.102985074627 | 0.024713370957 |
| 6 | 0.113432835821 | 0.0343338830723 |
| 7 | 0.119829424307 | 0.0423068785092 |
| 8 | 0.122388059701 | 0.0506102259718 |
| 9 | 0.122885572139 | 0.0571544479215 |
| 10 | 0.122388059701 | 0.0629408159497 |
| 11 | 0.121031207598 | 0.0676575352222 |
| 16 | 0.120335820896 | 0.0941542231187 |
| 21 | 0.122885572139 | 0.126040641884 |
| 26 | 0.127095292767 | 0.160259557501 |
| 31 | 0.128069330766 | 0.190365739974 |
| 36 | 0.128855721393 | 0.218778795533 |
| 41 | 0.128940662541 | 0.256367765626 |
| 46 | 0.131440622972 | 0.297542272455 |
+--------+-----------------+------------------+

testing

モデルの保存

学習と検証が終わったので、モデルを保存します。

1
model.save('recommend.model')

リコメンドさせてみる

先ほど作ったモデルを使いリコメンドさせてみます!
はじめに、先ほどのモデルを読み込みます。

1
model = tc.load_model('recommend.model')

そして、ユーザーID「3」の人が映画ID「1」を見たという感じでやっていきます。
(ユーザーID「15」, 「128」も同様)

1
2
3
4
5
data = tc.SFrame({
'userId': [3,15,128],
'movieId': [1,6,111]
})
print(data.join(movie, on='movieId'))
1
2
3
4
5
6
7
+---------+--------+--------------------+-------------------------------+
| movieId | userId | title | genres |
+---------+--------+--------------------+-------------------------------+
| 1 | 3 | Toy Story (1995) | Adventure|Animation|Childr... |
| 6 | 15 | Heat (1995) | Action|Crime|Thriller |
| 111 | 128 | Taxi Driver (1976) | Crime|Drama|Thriller |
+---------+--------+--------------------+-------------------------------+

では、リコメンドさせます(`・ω・´)

1
2
res = model.recommend([3, 15, 128], new_observation_data=data)
print(res.join(movie, on='movieId').sort('rank'))

結果

1
2
3
4
5
6
7
8
9
10
11
12
13
+--------+---------+-----------------+------+-------------------------------+-------------------------------+
| userId | movieId | score | rank | title | genres |
+--------+---------+-----------------+------+-------------------------------+-------------------------------+
| 3 | 2571 | 0.140675894239 | 1 | Matrix, The (1999) | Action|Sci-Fi|Thriller |
| 3 | 4993 | 0.128428682685 | 2 | Lord of the Rings: The Fel... | Adventure|Fantasy |
| 3 | 4963 | 0.120257125659 | 3 | Ocean's Eleven (2001) | Crime|Thriller |
| 15 | 1580 | 0.0189388030345 | 1 | Men in Black (a.k.a. MIB) ... | Action|Comedy|Sci-Fi |
| 15 | 103042 | 0.0183990796982 | 2 | Man of Steel (2013) | Action|Adventure|Fantasy|S... |
| 15 | 1923 | 0.0179402843312 | 3 | There's Something About Ma... | Comedy|Romance |
| 128 | 2797 | 0.0362989620521 | 1 | Big (1988) | Comedy|Drama|Fantasy|Romance |
| 128 | 1517 | 0.0334305414787 | 2 | Austin Powers: Internation... | Action|Adventure|Comedy |
| 128 | 1097 | 0.0305381224706 | 3 | E.T. the Extra-Terrestrial... | Children|Drama|Sci-Fi |
+--------+---------+-----------------+------+-------------------------------+-------------------------------+
  • ユーザーID「3」の人は、「Matrix」がおすすめされました。
  • ユーザーID「15」の人は、「Men in Black」がおすすめされました。
  • ユーザーID「128」の人は、「Big」がおすすめされました。

それっぽいものができたぞ(`・ω・´)

画像分類

次は、犬の画像分類を作ってみます(`・ω・´)
Core MLにエクスポートしてiPhoneのカメラで犬の写真を写して、
その犬の犬種を表示するというアプリを作ります。

訓練データ

こちらのデータを使いました。
http://vision.stanford.edu/aditya86/ImageNetDogs/

dog-data

モデルの読み込み

先ほどの犬の画像を読み込みます。
今回は「Border_terrier」,「cairn」,「Shih-Tzu」の3種類を判定するようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import turicreate as tc
def path2label(path):
if "Border_terrier" in path:
return "Border_terrier"
elif "cairn" in path:
return "cairn"
elif "Shih-Tzu" in path:
return "Shih-Tzu"
else:
return "unknown"
def gen_sframe():
data = tc.image_analysis.load_images('/dog', with_path=True)
data['label'] = data['path'].apply(path2label)
data.save('train.sframe')
data.explore()
gen_sframe()

読み込みますと、こんな感じに表示されます。

dog-data-view

学習

では、読み込んだデータをもとに学習させます!

1
2
3
4
5
6
7
8
9
10
11
12
import turicreate as tc
data = tc.SFrame('train.sframe')
train_data, test_data = data.random_split(0.8)
model = tc.image_classifier.create(train_data, target='label', max_iterations=100)
metrics = model.evaluate(test_data)
print(metrics['accuracy'])
model.save('dogs.model')
model.export_coreml('dogs.mlmodel')

結果は、こんな感じになりました!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 一部省略
--------------------------------------------------------
Number of examples : 557
Number of classes : 4
Number of feature columns : 1
Number of unpacked features : 2048
Number of coefficients : 6147
Starting L-BFGS
--------------------------------------------------------
+-----------+----------+-----------+--------------+-------------------+---------------------+
| Iteration | Passes | Step size | Elapsed Time | Training-accuracy | Validation-accuracy |
+-----------+----------+-----------+--------------+-------------------+---------------------+
| 1 | 4 | 0.000898 | 1.107175 | 0.786355 | 0.960000 |
| 2 | 7 | 0.500000 | 1.213239 | 0.885099 | 0.840000 |
| 3 | 8 | 0.500000 | 1.269205 | 0.919210 | 1.000000 |
| 4 | 9 | 0.500000 | 1.332011 | 0.951526 | 1.000000 |
| 5 | 10 | 0.500000 | 1.391532 | 0.971275 | 1.000000 |
| 6 | 11 | 0.500000 | 1.458173 | 0.978456 | 1.000000 |
| 11 | 16 | 0.500000 | 1.741182 | 0.996409 | 1.000000 |
| 25 | 30 | 0.500000 | 2.535394 | 1.000000 | 1.000000 |
+-----------+----------+-----------+--------------+-------------------+---------------------+
SUCCESS: Optimal solution found.

補足

先ほどのコードでは転移学習を使います。
なので、最初に転移学習用のデータのダウンロードに時間がかかります。

Core MLにエクスポート

学習が完了したので、Core MLに書き出します!

1
model.export_coreml('recommend.mlmodel')

coreml

Xcodeに入れる

書き出したモデルをXcodeにいれます。

xcode

結果

で、こんな感じになりました!

dog

それっぽいものができたぞ(`・ω・´)
が…訓練データが少ないのか反応がイマイチ…

まとめ

  • 数行〜数10行で作ることができる。(とっつきやすい)
  • これから機械学習を始める人には良いかも。
  • 本番でも耐えれるかは未検証なので、不安は残る。
  • 今後に期待(`・ω・´)

コードはGitHubで公開しています!

https://github.com/gupuru/turi-create-playground

ありがとうございました(`・ω・´)