rabbit-slide-kou-nagoya-rubykaigi-03 2017.2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.rabbit +1 -0
  3. data/README.rd +81 -0
  4. data/Rakefile +18 -0
  5. data/apache-arrow-gi-based-ruby-bindings.rab +766 -0
  6. data/config.yaml +27 -0
  7. data/data/hebi.svg +1108 -0
  8. data/data/hebi_blue.svg +1110 -0
  9. data/data/panda_kotatsu.svg +78 -0
  10. data/examples/data/bow.data.tf.filtered +0 -0
  11. data/examples/data/bow.data.tf.raw +0 -0
  12. data/examples/data/bow.data.tfidf.filtered +0 -0
  13. data/examples/data/bow.data.tfidf.raw +0 -0
  14. data/examples/data/bow.metadata.tf.filtered +1 -0
  15. data/examples/data/bow.metadata.tf.raw +1 -0
  16. data/examples/data/bow.metadata.tfidf.filtered +1 -0
  17. data/examples/data/bow.metadata.tfidf.raw +1 -0
  18. data/examples/data/topics.tf.filtered +0 -0
  19. data/examples/data/topics.tf.raw +0 -0
  20. data/examples/data/topics.tfidf.filtered +0 -0
  21. data/examples/data/topics.tfidf.raw +0 -0
  22. data/examples/estimate-topics.py +72 -0
  23. data/examples/raw-show-related-terms.rb +38 -0
  24. data/examples/raw-write-bow.rb +124 -0
  25. data/examples/read.rb +30 -0
  26. data/examples/run.sh +33 -0
  27. data/examples/show-related-terms.rb +39 -0
  28. data/examples/show.sh +20 -0
  29. data/examples/write-bow.rb +96 -0
  30. data/examples/write.py +15 -0
  31. data/images/clear-code.svg +161 -0
  32. data/images/copy-data-between-system.png +0 -0
  33. data/images/groonga-logo.svg +118 -0
  34. data/images/rroonga-logo.svg +117 -0
  35. data/images/share-data-between-system.png +0 -0
  36. data/images/system-with-ruby.png +0 -0
  37. data/pdf/nagoya-rubykaigi-03-apache-arrow-gi-based-ruby-bindings.pdf +0 -0
  38. data/theme.rb +6 -0
  39. metadata +113 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 00c1978e0d471f1f32ece9d0fba6f7c5685a5e9f
4
+ data.tar.gz: 1bde6cf49d82a6bb4b26ee8845da9bd90b0622e1
5
+ SHA512:
6
+ metadata.gz: 7f6696d3b16024c5e3c3f94282579414a1481b2f05274f91e27e2583c988628c157b0d1b1883abc69d5758ea7e70f4a9cb23149acf734f719e587f8ba607293f
7
+ data.tar.gz: ae574cf6d48bf431660f2d69e2bc25a331f2bb720ad492d9da3801a62a24b81adc30be06c3891582f7ee6d81efd76be0e095e7414309d7a69fa4b63ae99c2a3b
data/.rabbit ADDED
@@ -0,0 +1 @@
1
+ apache-arrow-gi-based-ruby-bindings.rab
@@ -0,0 +1,81 @@
1
+ = Apache ArrowのRubyバインディングをGObject Introspectionで
2
+
3
+ Apache Arrowはデータ分析を支援するライブラリーです。高速にデータにアクセスできる機能を提供します。重要なのは既存の多くのデータ分析関連プロダクトがApache Arrowと連携すると表明しているところです。RubyでもApache Arrowを使えるようになるとRubyでも既存のデータ分析関連プロダクトと連携できるようになります。そうなれるようにGObject Introspectionを使ってRubyからApache Arrowを使えるようにする方法を紹介します。
4
+
5
+ == ライセンス
6
+
7
+ === スライド
8
+
9
+ CC BY-SA 4.0
10
+
11
+ 原著作者名は以下の通りです。
12
+
13
+ * 須藤功平(またはKouhei Sutou)
14
+
15
+ === 画像
16
+
17
+ ==== Apache Arrow関連の画像
18
+
19
+ 以下の画像がApache Arrow関連の画像です。
20
+
21
+ * images/copy-data-between-system.png
22
+ * images/share-data-between-system.png
23
+ * images/system-with-ruby.png
24
+
25
+ Apache License 2.0
26
+
27
+ Copyright 2016 The Apache Software Foundation
28
+
29
+ ==== Groonga関連の画像
30
+
31
+ 以下の画像がGroonga関連の画像です。
32
+
33
+ * images/groonga-logo.svg
34
+ * images/rroonga-logo.svg
35
+
36
+ CC BY 3.0
37
+
38
+ 原著作者名は以下の通りです。
39
+
40
+ * Groongaプロジェクト
41
+
42
+ ==== クリアコード関連の画像
43
+
44
+ 以下の画像がクリアコード関連の画像です。
45
+
46
+ * images/clear-code.svg
47
+
48
+ CC BY-SA 4.0
49
+
50
+ 原著作者名は以下の通りです。
51
+
52
+ * クリアコード
53
+
54
+ ==== その他の画像
55
+
56
+ CC BY-SA 4.0
57
+
58
+ 原著作者名は以下の通りです。
59
+
60
+ * 須藤功平(またはKouhei Sutou)
61
+
62
+ == 作者向け
63
+
64
+ === 表示
65
+
66
+ rake
67
+
68
+ === 公開
69
+
70
+ rake publish
71
+
72
+ == 閲覧者向け
73
+
74
+ === インストール
75
+
76
+ gem install rabbit-slide-kou-nagoya-rubykaigi-03
77
+
78
+ === 表示
79
+
80
+ rabbit rabbit-slide-kou-nagoya-rubykaigi-03.gem
81
+
@@ -0,0 +1,18 @@
1
+ require "rabbit/task/slide"
2
+
3
+ # Edit ./config.yaml to customize meta data
4
+
5
+ spec = nil
6
+ Rabbit::Task::Slide.new do |task|
7
+ spec = task.spec
8
+ spec.files += Dir.glob("examples/**/*.*")
9
+ # spec.files += Dir.glob("doc/**/*.*")
10
+ # spec.files -= Dir.glob("private/**/*.*")
11
+ spec.add_runtime_dependency("rabbit-theme-clear-code")
12
+ end
13
+
14
+ desc "Tag #{spec.version}"
15
+ task :tag do
16
+ sh("git", "tag", "-a", spec.version.to_s, "-m", "Publish #{spec.version}")
17
+ sh("git", "push", "--tags")
18
+ end
@@ -0,0 +1,766 @@
1
+ = Apache Arrowの\nRubyバインディングを\nGObject Introspectionで
2
+
3
+ : author
4
+ 須藤功平
5
+ : institution
6
+ 株式会社クリアコード
7
+ : content-source
8
+ 名古屋Ruby会議03
9
+ : date
10
+ 2017-02-11
11
+ : allotted-time
12
+ 50m
13
+ : theme
14
+ .
15
+
16
+ = 内容
17
+
18
+ (1) まくら
19
+ (2) 本題
20
+ (3) オチ
21
+
22
+ = やりたいこと
23
+
24
+ Rubyで\n
25
+ データ分析
26
+
27
+ = データ分析?
28
+
29
+ いろいろある
30
+
31
+ = やりたいデータ分析
32
+
33
+ (('tag:center'))
34
+ 全文検索関連
35
+
36
+ * 同義語・関連語の自動抽出\n
37
+ 例:整数とIntegerは同じ
38
+ * 最近アツいキーワードの抽出
39
+ * ...
40
+
41
+ = 課題
42
+
43
+ * 道具が足りない
44
+ * ライブラリーがない・\n
45
+ メンテナンスされていない
46
+ * 道具が使いにくい
47
+
48
+ = 解決方法
49
+
50
+ やる\n
51
+ (('note:(道具を整備する)'))
52
+
53
+ = 世間の様子
54
+
55
+ * 主にJavaとPythonを使う
56
+ * 道具が揃っている
57
+ * 組み合わせてデータ分析
58
+
59
+ = 組み合わせた様子
60
+
61
+ # image
62
+ # src = images/copy-data-between-system.png
63
+ # relative_width = 100
64
+
65
+ (('note:https://arrow.apache.org/より(Apache License 2.0)'))
66
+
67
+ = 組み合わせの課題
68
+
69
+ * データ交換コストが高い
70
+ * データの直列化でCPUの8割を使用\n
71
+ by https://arrow.apache.org/
72
+
73
+ = 解決方法
74
+
75
+ データの\n
76
+ フォーマットを\n
77
+ 統一しよう!
78
+
79
+ = 統一した様子
80
+
81
+ # image
82
+ # src = images/share-data-between-system.png
83
+ # relative_width = 100
84
+
85
+ (('note:https://arrow.apache.org/より(Apache License 2.0)'))
86
+
87
+ = これはチャンス!
88
+
89
+ * RubyがArrow対応すると…
90
+ * 既存のシステムとやりとりできる
91
+ * 「この部分だけはRubyを使う」を\n
92
+ できる
93
+
94
+ = 一部でRuby
95
+
96
+ # image
97
+ # src = images/system-with-ruby.png
98
+ # relative_width = 100
99
+
100
+ (('note:前述の図を変更(Apache License 2.0)'))
101
+
102
+ = 一部でRubyを…使える?
103
+
104
+ 道具が\n
105
+ ないじゃん!
106
+
107
+ = 道具
108
+
109
+ # image
110
+ # src = images/rroonga-logo.svg
111
+ # relative_width = 100
112
+
113
+ (('note:Groongプロジェクト(CC BY 3.0)'))
114
+
115
+ = Rroonga
116
+
117
+ * 全文検索エンジン((*ライブラリー*))
118
+ * SQLで操作とかじゃなく\n
119
+ ((*オブジェクト*))として触れる
120
+
121
+ = オブジェクト例
122
+
123
+ 転置索引\n
124
+ オブジェクト
125
+
126
+ = 転置索引
127
+
128
+ (('tag:center'))
129
+ 雑な説明
130
+
131
+ * (({Hash}))みたいなもの
132
+ * キー:
133
+ * トークン(単語みたいなもの)
134
+ * 値:
135
+ * キー(トークン)を含む文書の一覧
136
+
137
+ = 転置索引オブジェクト(1)
138
+
139
+ # coderay ruby
140
+
141
+ index = Groonga["Words.index"]
142
+ token = "オブジェクト"
143
+ p index.estimate_size(token)
144
+ # => 19048
145
+ # 「オブジェクト」を含む文書は
146
+ # 約19048個ありそう
147
+
148
+ = 転置索引オブジェクト(2)
149
+
150
+ # coderay ruby
151
+
152
+ index.open_cursor(token) do |cursor|
153
+ # 最初の出現情報
154
+ posting = cursor.next
155
+ # 「オブジェクト」を含む最初の文書のID
156
+ p posting.record.id # => 17
157
+ # この文書が何個「オブジェクト」を含むか
158
+ p posting.term_frequency # => 1
159
+ # 文書の内容
160
+ puts posting.record.document
161
+ end
162
+
163
+ = 分析に使ってみよう
164
+
165
+ るりまを分析\n
166
+ ↓\n
167
+ 関連語を抽出
168
+
169
+ = 関連語の抽出方法例
170
+
171
+ (1) 文書を前処理
172
+ (2) 全文書をトピックに分類\n
173
+ * どんなトピックがあるかは学習
174
+ (3) 同じトピックで使われやすい\n
175
+ 単語を抽出\n
176
+ →関連語!
177
+
178
+ = 文書の前処理
179
+
180
+ 単語の出現頻度\n
181
+ (('note:(Bag of Wordsという)'))\n
182
+ に変換
183
+
184
+ = 単語の出現頻度
185
+
186
+ # coderay ruby
187
+ "名古屋マジ名古屋"
188
+ # ↓
189
+ {
190
+ "名古屋" => 2, # 2回
191
+ "マジ" => 1, # 1回
192
+ }
193
+
194
+ = 単語は数値に変換
195
+
196
+ # coderay ruby
197
+
198
+ # "名古屋" => 10
199
+ # "マジ" => 20
200
+ {
201
+ 10 => 2, # 「名古屋」2回
202
+ 20 => 1, # 「マジ」1回
203
+ }
204
+
205
+ = なんで数値にするの?
206
+
207
+ 計算しやすい
208
+
209
+ = Rroongaで前処理できる?
210
+
211
+ * 出現回数は求められる?
212
+ * 👌:(({posting.term_frequency}))
213
+ * 単語を数値に変換できる?
214
+ * 👌:全文検索エンジンの必須機能
215
+
216
+ = Rroongaで前処理(1)
217
+
218
+ # coderay ruby
219
+
220
+ bow = {} # 「名古屋」の分だけ
221
+ index.open_cursor("名古屋") do |cursor|
222
+ cursor.each do |posting|
223
+ record_id = posting.record_id
224
+ term_id = posting.term_id # "名古屋"のID
225
+ term_frequency = posting.term_frequency # 出現回数
226
+ bow[record_id] ||= {}
227
+ bow[record_id][term_id] = term_frequency
228
+ # bow: { # ↓実際は文字列じゃなくてID
229
+ # 2 => {"名古屋" => 9} # 文書2では9回出現
230
+ # 5 => {"名古屋" => 19} # 文書5では19回出現
231
+ # }
232
+ end
233
+ end
234
+
235
+ = Rroongaで前処理(2)
236
+
237
+ # coderay ruby
238
+
239
+ bow = {}
240
+ index.table.each do |token| # 全トークンを処理
241
+ index.open_cursor(token) do |cursor|
242
+ cursor.each do |posting|
243
+ # ...同じ...
244
+ end
245
+ end
246
+ end
247
+ # bow: { # 完成!
248
+ # 2 => {"名古屋" => 9, "マジ" => 2}
249
+ # 5 => {"名古屋" => 19, "寄席" => 1},
250
+ # ...
251
+ # }
252
+
253
+ = 前処理終わり
254
+
255
+ * 次はトピックに分類
256
+ * どんなトピックがあるかは学習
257
+
258
+ = トピックの学習方法
259
+
260
+ (('tag:center'))
261
+ (('tag:x-large'))
262
+ LDA\n
263
+ (('note:(Latent Dirichlet Allocation/潜在的ディリクレ配分法)'))
264
+
265
+ (('note:他にも色々ある'))\n
266
+ (('note:参考:http://www.ism.ac.jp/~daichi/lectures/H24-TopicModel/ISM-2012-TopicModels-daichi.pdf'))
267
+
268
+ = RubyでLDA
269
+
270
+ lda-ruby gem
271
+
272
+ = RubyでLDAをしない!
273
+
274
+ なぜなら!\n
275
+ Apache Arrowとか\n
276
+ GObject Introspectionの\n
277
+ 話をする\n
278
+ 機会がなくなるからだ!
279
+
280
+ = PythonでLDA
281
+
282
+ scikit-learn\n
283
+ (('note:(gensimの方がよく使われているかも)'))
284
+
285
+ = scikit-learnでLDA
286
+
287
+ # coderay python
288
+ import sklearn.decomposition
289
+ LDA = sklearn.decomposition.LatentDirichletAllocation
290
+ model = LDA(n_topics=100, # 100トピックに分類
291
+ learning_method="online",
292
+ total_samples=len(bag_of_words)) # 文書数
293
+ for words in bag_of_words: # 前処理結果
294
+ model.partial_fit(words) # 要フォーマット変換
295
+ model.components_ # ここに学習したトピックがある
296
+
297
+ = 前処理結果がない!
298
+
299
+ * 前処理はRubyでやった
300
+ * Python側にはない
301
+ * 前処理結果がないと\n
302
+ scikit-learnで分析できない!
303
+ * どうしよう!
304
+ * (('wait'))そうだ!Apache Arrowだ!
305
+
306
+ = Arrowでつながる世界
307
+
308
+ # image
309
+ # src = images/system-with-ruby.png
310
+ # relative_width = 100
311
+
312
+ (('note:(Apache License 2.0)'))
313
+
314
+ = RubyでArrow
315
+
316
+ * ArrowはC++のライブラリー
317
+ * Rubyからは使えない
318
+ * どうしよう!
319
+ * (('wait'))やる(バインディングを作る)
320
+
321
+ = Arrowのバインディング
322
+
323
+ * arrow-glib
324
+ * github.com/kou/arrow-glib
325
+ * Arrowのラッパー・C APIを提供
326
+ * GObject Introspection対応
327
+ * バインディングを実行時に生成
328
+
329
+ = 使い方:準備
330
+
331
+ # coderay ruby
332
+ require "gi"
333
+ Arrow = GI.load("Arrow")
334
+
335
+ = 使い方:配列を作る
336
+
337
+ # coderay ruby
338
+
339
+ # Arrowは高速に1次元・2次元配列を
340
+ # 扱うAPIを提供するライブラリー
341
+ builder = Arrow::UInt32ArrayBuilder.new
342
+ builder.append(29) # 要素追加
343
+ builder.append(9) # 要素追加
344
+ term_ids = builder.finish # 配列作成
345
+ p term_ids.length # => 2
346
+ p term_ids.get_value(0) # => 29
347
+ p term_ids.get_value(1) # => 9
348
+
349
+ = 少し…使いにくい!
350
+
351
+ * GObject Introspection
352
+ * だいたいいい感じになる!(('note:(すごい!)'))
353
+ * が!Ruby特有のところは一手間必要
354
+
355
+ = 使いやすさ検討
356
+
357
+ # coderay ruby
358
+
359
+ builder = Arrow::UInt32ArrayBuilder.new
360
+ builder.append(29)
361
+ builder.append(9)
362
+ term_ids = builder.finish
363
+ # ↓
364
+ term_ids =
365
+ Arrow::UInt32ArrayBuilder.build([29, 9])
366
+
367
+ = 一手間
368
+
369
+ # coderay ruby
370
+ class Arrow::ArrayBuilder
371
+ class << self
372
+ def build(values)
373
+ builder = new
374
+ values.each do |value|
375
+ builder.append(value)
376
+ end
377
+ builder.finish
378
+ end
379
+ end
380
+ end
381
+
382
+ = もう一手間
383
+
384
+ # coderay ruby
385
+
386
+ class Arrow::UInt32Array
387
+ class << self
388
+ def new(values)
389
+ UInt32ArrayBuilder.build(values)
390
+ end
391
+ end
392
+ end
393
+
394
+ = 一手間後
395
+
396
+ # coderay ruby
397
+
398
+ builder = Arrow::UInt32ArrayBuilder.new
399
+ builder.append(29)
400
+ builder.append(9)
401
+ term_ids = builder.finish
402
+ # ↓
403
+ term_ids = Arrow::UInt32Array.new([29, 9])
404
+
405
+ = さらに使いやすさ検討
406
+
407
+ # coderay ruby
408
+
409
+ p term_ids.get_value(0) # => 29
410
+ p term_ids.get_value(1) # => 9
411
+ # ↓
412
+ p term_ids[0] # => 29
413
+ p term_ids[1] # => 9
414
+
415
+ = 二手間
416
+
417
+ # coderay ruby
418
+ class Arrow::Array
419
+ def [](i)
420
+ get_value(i)
421
+ end
422
+ end
423
+
424
+ = もう一手間
425
+
426
+ # coderay ruby
427
+ class Arrow::Array
428
+ include Enumerable
429
+ def each
430
+ length.times do |i|
431
+ yield(self[i])
432
+ end
433
+ end
434
+ end
435
+
436
+ = 二手間後
437
+
438
+ # coderay ruby
439
+
440
+ p term_ids.get_value(0) # => 29
441
+ p term_ids.get_value(1) # => 9
442
+ # ↓
443
+ p term_ids.to_a # => [29, 9]
444
+
445
+ = 一手間はどこに書くの?
446
+
447
+ # coderay ruby
448
+
449
+ # こう?
450
+ require "gi"
451
+ Arrow = GI.load("Arrow")
452
+ module Arrow
453
+ class Array
454
+ # ...
455
+ end
456
+ end
457
+
458
+ = 違う!
459
+
460
+ * (({GI.load}))はデモ用のAPI
461
+ * ちゃんと作るときは使わない
462
+ * (({GI::Loader}))を継承
463
+ * (({#post_load}))フック時に一手間
464
+
465
+ = (({GI::Loader#post_load}))
466
+
467
+ # coderay ruby
468
+
469
+ class Arrow::Loader < GI::Loader
470
+ private
471
+ def post_load(*args)
472
+ require "arrow/array"
473
+ require "arrow/array-builder"
474
+ end
475
+ end
476
+
477
+ = (({arrow/array.rb}))
478
+
479
+ # coderay ruby
480
+
481
+ class Arrow::Array
482
+ include Enumerable
483
+ def each
484
+ length.times do |i|
485
+ yield(self[i])
486
+ end
487
+ end
488
+ end
489
+
490
+ = (({arrow.rb}))
491
+
492
+ # coderay ruby
493
+
494
+ require "arrow/loader"
495
+ module Arrow
496
+ Loader.load("Arrow", self)
497
+ # ↑の中で#post_loadが呼ばれる
498
+ end
499
+
500
+ = 使い方
501
+
502
+ # coderay ruby
503
+
504
+ require "arrow"
505
+
506
+ term_ids = Arrow::UInt32Array.new([29, 9])
507
+ p term_ids.to_a # => [29, 9]
508
+
509
+ = すごい!
510
+
511
+ Rubyっぽい!
512
+
513
+ = 実装
514
+
515
+ * RArrow
516
+ * github.com/kou/rarrow
517
+ * (('note:RのArrowバインディングみたいでアレかもしれない'))
518
+ * 他の一手間例もアリ
519
+ * 例:(({.open {|io| ...}}))で自動(({close}))
520
+
521
+ = 前処理結果を渡す
522
+
523
+ * 忘れていたでしょ?
524
+ * Arrowの話をしていたのはこのため
525
+ * 手順
526
+ (1) Rubyで書き出し
527
+ (2) Pythonで読み込み
528
+
529
+ = Rubyで書き出し
530
+
531
+ # coderay ruby
532
+
533
+ FOS = Arrow::IO::FileOutputStream # 長いから
534
+ SW = Arrow::IPC::StreamWriter # 長いから
535
+ FOS.open("/tmp/bow", false) do |output_stream|
536
+ # schema:カラム名と型の定義(省略)
537
+ SW.open(output_stream, schema) do |writer|
538
+ bow.each do |record_id, words|
539
+ # record_batch(省略):
540
+ # テーブルからN行だけ抜き出したもの
541
+ writer.write_record_batch(record_batch)
542
+ end
543
+ end
544
+ end
545
+
546
+ = Pythonで読み出し
547
+
548
+ # coderay python
549
+
550
+ from scipy.sparse import csr_matrix
551
+ import pandas as pd
552
+ import pyarrow as A
553
+ with A.io.MemoryMappedFile("/tmp/bow", "rb") as source:
554
+ reader = A.ipc.StreamReader(source)
555
+ for record_batch in reader: # ストリームで順に処理
556
+ # Pandasのデータフレームに変換(ゼロコピー!)
557
+ df = record_batch.to_pandas()
558
+ # 疎な行列に変換
559
+ corpus = csr_matrix((df["score"].values,
560
+ df["term_id"].values,
561
+ [0, df["term_id"].size]),
562
+ shape=(1, n_features))
563
+ model.partial_fit(corpus) # 学習
564
+
565
+ = トピックを確認
566
+
567
+ # coderay python
568
+
569
+ for topic in model.components_:
570
+ n_top_terms = 10
571
+ # このトピックに関連している
572
+ # 上位10単語を計算
573
+ top_term_indexes = # ↓[::-1]でreverse
574
+ topic.argsort()[:-n_top_terms-1:-1]
575
+ for i in top_term_indexes:
576
+ term_id = i # 単語ID
577
+ score = topic[i] # 関連度
578
+ print("%s:%s" % (term_id, score))
579
+
580
+ = 単語IDじゃわからん!
581
+
582
+ * 単語はIDにして計算した
583
+ * けど、確認は単語でしたい!
584
+ * 単語とIDの管理は…Rroonga!
585
+ * トピックをRubyに持っていかないと
586
+ * (('wait'))そうだ!Apache Arrowだ!
587
+
588
+ = Arrowでつながる世界
589
+
590
+ # image
591
+ # src = images/system-with-ruby.png
592
+ # relative_width = 100
593
+
594
+ (('note:(Apache License 2.0)'))
595
+
596
+ = Pythonで書き出し
597
+
598
+ # coderay python
599
+
600
+ with open("/tmp/topics", "wb") as sink:
601
+ # schema:batch.schemaで取得できる(省略)
602
+ writer = A.ipc.StreamWriter(sink, schema)
603
+ def topic_to_df(topic):
604
+ # 前述のトピックを確認した処理と同じ
605
+ values = [[i, topic[i]]
606
+ for i in topic.argsort()[:-10-1:-1]]
607
+ return pd.DataFrame(values,
608
+ columns=["term_id", "score"])
609
+ for topic in model.components_:
610
+ df = topic_to_df(topic)
611
+ batch = A.RecordBatch.from_pandas(df)
612
+ writer.write_batch(batch)
613
+ writer.close()
614
+
615
+ = Rubyで読み込み
616
+
617
+ # coderay ruby
618
+
619
+ MMF = Arrow::IO::MemoryMappedFile # 長いから
620
+ SR = Arrow::IPC::StreamReader # 長いから
621
+ MMF.open("/tmp/topics", :read) do |input|
622
+ SR.open(input) do |reader|
623
+ reader.each do |record_batch|
624
+ record_batch.each do |record|
625
+ # 単語IDを単語に変換
626
+ term = index.table[record["term_id"]]
627
+ p [term, record["score"]]
628
+ end
629
+ end
630
+ end
631
+ end
632
+
633
+ = 実際の結果
634
+
635
+ 1: uzqpuaglzig, あきらめ, ご覧
636
+ 2: useloopback, タスク
637
+ 3: プラットホーム, mydog
638
+ 4: delegateclass, barbar
639
+ ...
640
+
641
+ (('tag:center'))
642
+ (('wait'))微妙…
643
+
644
+ = 大事なこと
645
+
646
+ Garbage in,\n
647
+ Garbage out
648
+
649
+ = 前処理をがんばる
650
+
651
+ * いらない文書を無視
652
+ * いらないトークンを無視
653
+
654
+ = いらない文書を無視
655
+
656
+ # coderay ruby
657
+
658
+ entries = Groonga["Entries"]
659
+ # 全文検索エンジンで検索するので高速!すごい!
660
+ target_entries = entries.select do |record|
661
+ (record.version == "2.4.0") -
662
+ (record.document =~ "@todo")
663
+ # ↑@todoな文書を対象外
664
+ end
665
+ # ... do |posting|
666
+ # 存在チェックも全文検索エンジンがやるので高速!
667
+ next if target_entries.key?(posting.record_id)
668
+ # ... end
669
+
670
+ = いらないトークンを無視
671
+
672
+ # coderay ruby
673
+
674
+ n_entries = target_entries.size
675
+ # ほとんどの文書に含まれるなら重要じゃない
676
+ too_many_threshold = n_entries * 0.9
677
+ # ごく一部の文書にしか含まれないなら重要じゃない
678
+ too_less_threshold = n_entries * 0.01
679
+ # ... do |term|
680
+ n_match_documents = index.estimate_size(term)
681
+ next if n_match_documents >= too_much_threshold
682
+ next if n_match_documents <= too_less_threshold
683
+ # ... end
684
+
685
+ = 実際の結果
686
+
687
+ 1: self, ブロック
688
+ 2: each, enumerator
689
+ 3: integer, 整数, 表示
690
+ 4: ruby, object
691
+ ...
692
+
693
+ (('tag:center'))
694
+ (('wait'))それっぽくなってきた!
695
+
696
+ = まとめ(1)
697
+
698
+ * Rubyでデータ分析
699
+ * 全部はムリ
700
+ * でも一部ならいける
701
+
702
+ = まとめ(2)
703
+
704
+ * 一部ならいけるのは…
705
+ * Apache Arrowの登場\n
706
+ データ交換しやすくなる
707
+ * Rroongaの存在\n
708
+ Rubyで高速に自然言語処理できる
709
+
710
+ = まとめ(3)
711
+
712
+ * RubyでApache Arrow
713
+ * バインディングが必要
714
+ * GObject Introspection\n
715
+ ベースで作った(arrow-glib)
716
+
717
+ = まとめ(4)
718
+
719
+ * GObject Introspection
720
+ * だいたいいい感じ
721
+ * さらに一手間でグッとよくなる
722
+
723
+ = まとめ(5)
724
+
725
+ * 実際に分析してみた
726
+ * Rubyで前処理\n
727
+ ↓Arrow
728
+ * Pythonで分析\n
729
+ ↓Arrow
730
+ * Rubyで確認\n
731
+ (('note:(本当は全文検索用DBに入れて活用する)'))
732
+
733
+ = まとめ(6)
734
+
735
+ * Rubyでデータ分析いけそう!
736
+ * Arrowでデータの受け渡しが容易に\n
737
+ →分析処理へのRubyの参加が容易に
738
+ * RroongaでRubyでも高速に\n
739
+ 自然言語処理をできる
740
+
741
+ = おしらせ(1)
742
+
743
+ * Rubyでデータ分析したい人は\n
744
+ クリアコードに相談してね!
745
+ * 道具の用意・活用を手伝える
746
+
747
+ # image
748
+ # src = images/clear-code.svg
749
+ # relative_width = 100
750
+
751
+ = おしらせ(2)
752
+
753
+ * Groonga Meatup名古屋2017
754
+ * 時間:明日の午前(10:00-)
755
+ * 場所:Misoca
756
+
757
+ # image
758
+ # src = images/groonga-logo.svg
759
+ # relative_height = 100
760
+
761
+ = 別案
762
+
763
+ * RroongaのPython版を作る
764
+ * RubyもArrowも必要なくなる…
765
+ * けど、より高速に前処理できる!
766
+ * (('wait'))Cythonで作ろうかと思っている…