SlideShare a Scribd company logo
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Data Tools
楽しく実装すればいいじゃんねー
須藤功平
株式会社クリアコード
沖縄Ruby会議02
2018-03-10
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Data Tools
プロジェクト
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
実現したいこと
Rubyで
データ処理
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
やっていること
データ処理用の
ツールの開発
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
開発例
各種フォーマットを扱うgem
Apache Arrow, Apache Parquet, CSV, ...✓
✓
各種パッケージの用意
deb, RPM, Homebrew, ...✓
✓
...✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
この話の目的
勧誘一緒に開発しようぜ!
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
勧誘方法
プロジェクトのポリシーを紹介
一緒に活動したくなる!✓
✓
開発の具体例を紹介
一緒に開発したくなる!✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ポリシー1
Rubyコミュニティーを
超えて協力する
もちろんRubyコミュニティーとも協力する
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Rubyに閉じずに協力
他の言語は敵ではない
他の言語がよくなることは
Rubyがなにかを失うことではない
✓
✓
みんなよくなったらいいじゃん
Rubyも他の言語も✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
協力例
Apache Arrow
Pythonの人達他と一緒に
C/C++のライブラリーを開発
それぞれでバインディングを開発✓
それぞれで同じライブラリーを活用✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ポリシー2
非難することよりも
手を動かすことが大事
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
非難しない
そんなことを
している
時間はない
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
手を動かす
これ、よくないなー
よくすればいいじゃんねー✓
✓
これがないからなー
作ればいいじゃんねー✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ポリシー3
一回だけの活発な活動より
小さくても
継続的に活動することが
大事
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
一回だけの活発な活動
○○作ったよ!どーん!
すごい!✓
…数年後…今動かないんだよね…✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
継続的な活動
ちまちま○○作ってるんだー!
がんばってね!今後に期待!✓
…数年後…これは…使える!✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
継続的な活動のために
がんばり過ぎない
短距離走ではなくマラソン✓
途中で休んだっていい✓
✓
1人で抱え込まない
みんなでやれば途中で休みやすい✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ポリシー4
現時点での知識不足は
問題ではない
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
知識不足?
高速な実装の実現
プログラミング・数学などの
高度な知識は便利
✓
✓
今すごい人でも
最初はなにも知らなかった
「今知らないこと」は
「始めない理由」にはならない
✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
私たちは学べる
知識は身につく
活動していく中で自然と✓
✓
学び方
OSSの既存実装から学習✓
ドキュメントを読む✓
他の人から教えてもらう✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ポリシー5
部外者からの非難は
気にしない
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
部外者からの非難
Rubyで頑張ってもアレだよねー
とか
無視する✓
✓
対応している時間はない✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ポリシー6
楽しくやろう!
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
楽しむ
使っているのは
Rubyだから!
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ポリシー
Ruby外とも協力✓
非難するより手を動かす✓
継続的な活動✓
知識不足は問題ない✓
外からの非難は気にしない✓
楽しくやろう!✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
開発例
ツールの紹介ではない✓
実装の紹介
開発中におっと思ったやつとか✓
紹介したいやつとか✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
開発例1
csv
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
csv
CSVの読み書きライブラリー✓
2003年から標準添付✓
2018年からメンテナンスを引取✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
digを追加したとき
https://github.com/ruby/csv/pull/15
CSV::Table#dig✓
CSV::Row#dig✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
digの作り方
def dig(index, *indexes)
# ここだけ違う
value = find_value(index)
# ↓は共通
return nil if value.nil?
return value if indexes.empty?
value.dig(*indexes)
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
CSV::Rowでのfind_value
row[index] # => field value
digの中ではselfの[]を呼べばよい
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
[]の呼び方
def dig(index, *indexes)
# インスタンスメソッドでは
# selfを省略できるからこう?
value = [index]
# ↑は配列リテラル
# ...
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
[]の呼び方
def dig(index, *indexes)
# こういうときこそsendで  
# メソッド呼び出し
value = send(:[], index)
# 動く
# ...
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
[]の呼び方
def dig(index, *indexes)
# row[index]みたいに書けば 
# よかった
value = self[index]
# もちろん動く
# ...
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
selfの[]の呼び方
自分も昔悩んだ気がする✓
懐かしかったので紹介✓
みんなで開発🠊気づきやすい✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
開発例2
Red Datasets
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Datasets
データを簡単に使えるように!✓
実験・開発に便利✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
例:日本語データ欲しい!
require "datasets"
# 日本語版Wikipediaの記事データ
options = {language: :ja, type: :articles}
dataset = Datasets::Wikipedia.new(options)
dataset.each do |page| # 全ページを順に処理
p page.title # タイトル
p page.revision.text # 本文
end
# インターフェイスがeachなのがカッコいいんだよ!
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
実装方法
データのダウンロード1.
データのパース2.
順にyield3.
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ダウンロード
require "open-uri"
open("https://...") do |input|
File.open("...", "wb") do |output|
IO.copy_stream(input, output)
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
途中でエラーになったら?
やり直し
または
再開
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
再開
HTTP
range request
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
HTTP range request
リクエスト
Range: bytes=#{start}-✓
✓
レスポンス
206 Partial Content✓
Content-Range: bytes ...✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
open-uriとrange request
open-uriはrange request未対応
出力無関係のAPIだからしょうがない✓
✓
どうなるのがいいだろう?
今度田中さんに相談しよう✓
Red Data ToolsはRubyもよくしたい
ポリシー1:コミュニティーを超えて協力
✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
open-uriでrange request
# 文字列キーはHTTPヘッダーになる
options = {"Range" => "bytes=#{start}-"}
open("...", options) do |input|
# レスポンスが200か206かはわからない
File.open("...", "ab") do |output|
IO.copy_stream(input, output)
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
大きなデータの扱い
時間がかかる✓
あとどのくらいか気になる
ちゃんと動いているよね…?✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
あとどのくらい?
プログレスバー
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
プログレスバーの実装
n = 40
1.upto(n) do |i|
print("r|%-*s|" % [n, "*" * i])
sleep(0.1)
end
puts
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
sprintfフォーマット
%-*s
%:フォーマット開始✓
-:左詰め✓
*:引数で幅を指定✓
s:対象は文字列✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
sprintfフォーマット
"%-*s" % [n, "*" * i]
幅はn桁✓
"*" * iを左詰め✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
open-uriでプログレスバー
length = nil
progress = lambda do |current|
ratio = current / length.to_f
print("r|%-10s|" % ["*" * (ratio * 10).ceil])
end
open(uri,
content_length_proc: ->(l) {length = l},
progress_proc: progress) do |input|
# ...
end
puts
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
もっとプログレスバー
バックグランド化したら?
表示して欲しくない
ヒント:プロセスグループ
✓
✓
リダイレクトしているときは?
表示して欲しくない
ヒント:IO#tty?
✓
✓
プログレスバーの表示幅は?
ヒント:io/console/size
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
開発例3
Apache Arrow
Red Arrow
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Apache Arrow
インメモリーデータ分析用
データフォーマット
ほぼ固まってきた
✓
インメモリーデータ分析用
高速なデータ操作実装
徐々に実装が始まっている
✓
今、すごくアツい!✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Apache Arrowの特徴
データ交換コストが低い
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
低データ交換コスト
複数システムで協力しやすい
Rubyでデータ取得🠊Pythonで分析✓
✓
徐々にRubyを使えるところを
増やせる
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Apache Arrowの利用例
Scala Python
Apache Spark✓
✓
CPU GPU
https://github.com/gpuopenanalytics/libgdf✓
✓
CPU FPGA
https://github.com/johanpel/fletcher✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Apache ArrowをRubyでも!
バインディングを本体で開発
本体の開発チームに入った✓
GObject Introspection(GI)を利用✓
✓
GIを使うとRuby以外のバインディングも
自動生成できる
ポリシー1:コミュニティーを超えて協力
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrow
Apache Arrowの
Rubyバインディング
✓
GIベースのバインディングに
Ruby特有の機能をプラス
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Ruby特有の機能例
スライスAPI
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
スライス
データの一部を切り出す
(0..10).to_a.slice(2)
# => 2
(0..10).to_a.slice(2..4)
# => [2, 3, 4]
(0..10).to_a.slice(2, 4)
# => [2, 3, 4, 5]
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowのスライス
table.slice(2)
# 2行目だけのテーブル
# Array#sliceと違う
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowのスライス
table.slice(2..4)
# 2,3,4行目だけのテーブル
# Array#sliceと同じ
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowのスライス
table.slice(2, 4)
# 2,4行目だけのテーブル
# Array#sliceと違う
table.slice(2, 4, 6, 8)
# 2,4,6,8行目だけのテーブル
# Array#sliceと違う
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowのスライス
table.slice([2, 4])
# 2,3,4,5行目だけのテーブル
# Array#slice(2, 4)と同じ
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowのスライス
table.slice([true, false] * 5)
# 0,2,4,6,8行目だけのテーブル
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowのスライス
table.slice do |slicer|
slicer.price >= 500
end
# priceカラムの値が500以上の
# 行だけのテーブル
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowのスライス
table.slice do |slicer|
(slicer.price >= 500) &
(slicer.is_published)
end
# priceカラムの値が500以上かつ
# is_publishedカラムの値がtrueの
# 行だけのテーブル
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowのスライス
Active Recordみたいなfluent intefaceより
もブロック内で式を書く方がRubyっぽいん
じゃないかと思うんだよねー
fluent interfaceはORを書きにくいからさー
Fluent interface:
http://bliki-ja.github.io/FluentInterface/
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ブロック内で条件式
class Arrow::Table
# table.slice {|slicer| ...}の実現
def slice(*slicers)
if block_given?
slicer = yield(Slicer.new(self))
slicers << slicer.evaluate
end
# ...
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ブロック内で条件式
class Arrow::Slicer
def initialize(table)
@table = table
end
# slicer.priceの実現
def method_missing(name, *args, &block)
ColumnCondition.new(@table[name])
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ブロック内で条件式
class ColumnCondition < Condition
def initialize(column)
@column = column
end
# slicer.price >= 500の実現
def >=(value)
GreaterEqualCondition.new(@column, value)
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ブロック内で条件式
class GreaterEqualCondition < Condition
def initialize(column, value)
@column = column
@value = value
end
# slicer.price >= 500を評価
def evaluate
# ホントはC++で実装
@column.collect {|value| value >= @value}
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ブロック内で条件式
class Condition
# (slicer.price >= 500) & (...)の実現
def &(condition)
AndCondition.new(self, condition)
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
条件式のポイント
遅延評価
各要素毎にブロックを評価✓
ブロックは一回だけ評価✓
ブロックで指定した条件は
コンパイルしてC++実装で実行
✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowと外の世界
ハブになるといいかも!
各種データと変換可能に✓
各種オブジェクトと変換可能に✓
✓
Ruby間の連携を推進
今は互換性がないライブラリー
🠊連携できるように!
✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
データ変換
Arrow::Table.load
データの読み込み✓
✓
Arrow::Table#save
データの書き出し✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
データ変換例
# CSVを読み込んで
table = Arrow::Table.load("a.csv")
# Arrowで保存
table.save("a.arrow")
# Parquetで保存
table.save("a.parquet")
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
CSVの読み込み
CSVは広く使われている
CSVなデータを簡単に使えると捗る✓
✓
難しいところ
データ定義が緩い
例:カラムの型情報がない
✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowでの読み込み
2パスで処理
全部処理して各カラムの型を推定a.
推定した型でArrowのデータに変換b.
✓
時間がかかる
読み込んだデータを別の形式に変換して再利用す
る使い方を想定
だから、まぁ、いいかなぁって
✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
型の推定
candidate = nil
column.each do |value|
case value
when nil; next # ignore
when "true", "false", true, false; c = :boolean
when Integer; c = :integer
# ...
else; c = :string # わからなかったら文字列
end
candidate ||= c
candidate = :string if candidate != c # 混ざったら文字列
break if candidate == :string # 文字列なら終わり
end
candidate || :string # わからなかったら文字列
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
オブジェクト変換
Numo::NArray, NMatrix
既存の多次元配列オブジェクト✓
✓
PyCall経由でPyArrow
Rubyでデータ作成🠊Pythonで処理✓
✓
GDK Pixbuf
画像オブジェクト✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
オブジェクト変換例1
# PNG画像を読み込み
pixbuf = GdkPixbuf::Pixbuf.new(file: "a.png")
# Arrow経由でNumo::NArrayに変換
narray = pixbuf.to_arrow.to_narray
# 不透明に(アルファ値(透明度)を0xffに)
narray[true, true, 3] = 0xff
# Arrow経由でGdkPixbuf::Pixbufに変換
no_alpha_pixbuf = narray.to_arrow.to_pixbuf
# GIF画像として保存
no_alpha_pixbuf.save(filename: "a-no-alpha.gif")
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Pixbuf→Arrow
class GdkPixbuf::Pixbuf
def to_arrow
bytes = read_pixel_bytes # ピクセル値
buffer = Arrow::Buffer.new(bytes)
# 高さ、幅、チャンネル数の3次元配列
# チャンネル数:RGBAだと4チャンネル
shape = [height, width, n_channels]
# バイト列なのでUInt8
Arrow::Tensor.new(Arrow::UInt8DataType.new,
buffer, shape)
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
ゼロコピーの実現
ゼロコピー
同じメモリー領域を参照し、
コピーせずに同じデータを利用
✓
速い!!!✓
✓
データ
バイト列へのポインター✓
RubyではRSTRING_PTR(string)✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Stringとゼロコピー
/* pointerの内容をコピー */
rb_str_new(pointer, size);
/* pointerの内容を参照:ゼロコピー */
rb_str_new_static(pointer, size);
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
StringとゼロコピーとGC
arrow_data = /* ... */;
/* ゼロコピー */
rb_str_new_static(arrow_data, size);
/* arrow_dataはいつ、だれが開放? */
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Rubyでゼロコピー
rb_str_new_static()だけ
メモリー管理できない✓
✓
メモリー管理する何かが必要✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Arrowでゼロコピー
GBytesを利用✓
GBytes
GLib提供のバイト列オブジェクト✓
リファレンスカウントあり✓
✓
RubyだとGLib::Bytes✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
GLib::Bytes#to_s
static VALUE rgbytes_to_s(VALUE self) {
GBytes *bytes = RVAL2BOXED(self, G_TYPE_BYTES);
gsize size;
gconstpointer data =
g_bytes_get_data(bytes, &size);
/* ゼロコピーでASCII-8BITな文字列を生成 */
VALUE rb_data = rb_enc_str_new_static(
data, size, rb_ascii8bit_encoding());
rb_iv_set(rb_data, "@bytes", self); /* GC対策 */
return rb_data;
}
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
GLib::Bytes#initialize
static VALUE rgbytes_initialize(VALUE self, VALUE rb_data) {
const char *pointer = RSTRING_PTR(rb_data);
long size = RSTRING_LEN(rb_data);
GBytes *bytes;
if (RB_OBJ_FROZEN(rb_data)) { /* ゼロコピー */
bytes = g_bytes_new_static(pointer, size);
rb_iv_set(self, "source", rb_data); /* GC対策 */
} else { /* コピー */
bytes = g_bytes_new(pointer, size);
}
G_INITIALIZE(self, bytes);
return Qnil;
}
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
GBytesはすでに使っていた
class GdkPixbuf::Pixbuf
def to_arrow
# ピクセル値はGLib::Bytes
bytes = read_pixel_bytes
buffer = Arrow::Buffer.new(bytes)
shape = [height, width, n_channels]
Arrow::Tensor.new(Arrow::UInt8DataType.new,
buffer,
shape)
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
オブジェクト変換例2
# RelationをArrow形式に
users = User
.where("age >= ?", 20)
.to_arrow
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Relation→Arrow
module ArrowActiveRecord::Arrowable
def to_arrow(batch_size: 10000)
in_batches(of: batch_size).each do |relation|
column_values_set = relation.pluck(*column_names).transpose
data_types.each_with_index do |data_type, i|
column_values = column_values_set[i]
arrow_batches[i] << build_arrow_array(column_values, data_type)
end
end
# ...
Arrow::Table.new(...)
end
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Chainer
ChainerのRuby移植
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Chainer
深層学習フレームワーク
Pythonのみで実装✓
✓
移植しやすい
Pythonのみで実装されているから✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Red Chainerサンプル
model = Chainer::Links::Model::Classifier.new(MLP.new(args[:unit], 10))
optimizer = Chainer::Optimizers::Adam.new
optimizer.setup(model)
train, test = Chainer::Datasets::Mnist.get_mnist
train_iter = Chainer::Iterators::SerialIterator.new(train, args[:batchsize])
test_iter = Chainer::Iterators::SerialIterator.new(test, args[:batchsize], repeat: false, shuffle: false)
# ...
横に長い
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Chainerのサンプル
import chainer
import chainer.links as L
model = L.Classifier(MLP(args.unit, 10))
optimizer = chainer.optimizers.Adam()
optimizer.setup(model)
train, test = chainer.datasets.get_mnist()
train_iter = chainer.iterators.SerialIterator(train, args.batchsize)
test_iter = chainer.iterators.SerialIterator(test, args.batchsize,
repeat=False, shuffle=False)
こっちも横に長い
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Pythonでの短く仕方
# 通常
import chainer
model = chainer.links.Classifier(MLP(args.unit, 10))
# Lでショートカット
import chainer.links as L
model = L.Classifier(MLP(args.unit, 10))
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Rubyでの短く仕方
# 通常
model = Chainer::Links::Model::Classifier.new(...)
# Lでショートカット
L = Chainer::Links
model = L::Model::Classifier.new(...)
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
PythonとRubyの違い
Python
ファイル内でだけLが有効✓
ファイル単位でネームスペース✓
✓
Ruby
グローバルにLが有効✓
微妙!✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Rubyらしく短く
# Rubyのネームスペースの仕組みはモジュール
Module.new do
include Chainer::Links
model = Model::Classifier.new(...)
end
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
開発したくなった?
楽しそう!
一緒に開発しようぜ!✓
✓
やっぱRubyでデータ扱いたい!
一緒に開発しようぜ!✓
✓
レベルアップしたい!
一緒に開発しようぜ!✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
レベルアップへの道
NG集をたくさん覚える✓
よいコードにたくさん触れる✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
よいコード
Red Data Toolsに
たくさんある!
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
一緒に開発
どこからでもオンラインで
GitHubとGitter(チャット)を使用✓
✓
東京は月一オフラインで
「OSS Gate Red Data Tools」✓
✓
Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2
Join Red Data Tools!
Webサイト
https://red-data-tools.github.io/ja/✓
✓
Gitter(チャット)
https://gitter.im/red-data-tools/ja✓
✓
GitHub
https://github.com/red-data-tools/✓
✓

More Related Content

PDF
RubyもApache Arrowでデータ処理言語の仲間入り
PDF
Rubyと仕事と自由なソフトウェア
PDF
Apache ArrowのRubyバインディングをGObject Introspectionで
PDF
Mobage を支える Ruby の技術 ~ 複数DB編 ~
PDF
今注目のSpark SQL、知っておきたいその性能とは 20151209 OSC Enterprise
PDF
InfluxDB の概要 - sonots #tokyoinfluxdb
PDF
Apache Arrow
PDF
[Postgre sql9.4新機能]レプリケーション・スロットの活用
RubyもApache Arrowでデータ処理言語の仲間入り
Rubyと仕事と自由なソフトウェア
Apache ArrowのRubyバインディングをGObject Introspectionで
Mobage を支える Ruby の技術 ~ 複数DB編 ~
今注目のSpark SQL、知っておきたいその性能とは 20151209 OSC Enterprise
InfluxDB の概要 - sonots #tokyoinfluxdb
Apache Arrow
[Postgre sql9.4新機能]レプリケーション・スロットの活用

What's hot (20)

PPTX
Hadoop Troubleshooting 101 - Japanese Version
PDF
PDF
MapReduce/YARNの仕組みを知る
PPT
クラウド時代の並列分散処理技術
PDF
MapReduce/Spark/Tezのフェアな性能比較に向けて (Cloudera World Tokyo 2014 LT講演)
PDF
コンテナーによるIT基盤変革 - IT infrastructure transformation -
PDF
各スペシャリストがお届け!データベース最新情報セミナー -PostgreSQL10-
PDF
PDF
Apache Arrow
PPTX
Tokyo Webmining #12 Hapyrus
PDF
Apache Arrow 2019
PDF
Fluentd meetup #2
PDF
ビッグデータ活用とサーバー基盤
PDF
AI・HPC・ビッグデータで利用される分散ファイルシステムを知る
PDF
Apache Arrow 1.0 - A cross-language development platform for in-memory data
PPTX
Hadoop -ResourceManager HAの仕組み-
PDF
Jpug study-pq 20170121
PDF
MapReduce入門
Hadoop Troubleshooting 101 - Japanese Version
MapReduce/YARNの仕組みを知る
クラウド時代の並列分散処理技術
MapReduce/Spark/Tezのフェアな性能比較に向けて (Cloudera World Tokyo 2014 LT講演)
コンテナーによるIT基盤変革 - IT infrastructure transformation -
各スペシャリストがお届け!データベース最新情報セミナー -PostgreSQL10-
Apache Arrow
Tokyo Webmining #12 Hapyrus
Apache Arrow 2019
Fluentd meetup #2
ビッグデータ活用とサーバー基盤
AI・HPC・ビッグデータで利用される分散ファイルシステムを知る
Apache Arrow 1.0 - A cross-language development platform for in-memory data
Hadoop -ResourceManager HAの仕組み-
Jpug study-pq 20170121
MapReduce入門
Ad

Similar to Red Data Tools (20)

PDF
Ruby 2.5
PDF
Ruby紹介
PDF
マニアックなRuby 2.7新機能紹介
PDF
Rubyの黒魔術
PDF
Ruby 3の型推論やってます
PDF
桐島、Rubyやめるってよ
PDF
Ruby開発が教えてくれたこと
PDF
メイカーRuby講習会2013
PDF
組込み向けRuby処理系mrubyの可能性
PDF
Ruby でつくる型付き Ruby
PDF
全文検索でRedmineをさらに活用!
PDF
Rubyを使った分散全文検索ミドルウェア
PDF
What's Cooking In Ruby 2.7
ODP
20090704rubyist九州
PDF
はじめてのRuby拡張ライブラリ
PPTX
Couch Db勉強会0623 by yssk22
PDF
nomlab_okayamaruby_slide
PDF
Code Anything
PDF
アプリケーションへのRubyインタープリターの組み込み
PDF
社会ネットワーク分析第7回
Ruby 2.5
Ruby紹介
マニアックなRuby 2.7新機能紹介
Rubyの黒魔術
Ruby 3の型推論やってます
桐島、Rubyやめるってよ
Ruby開発が教えてくれたこと
メイカーRuby講習会2013
組込み向けRuby処理系mrubyの可能性
Ruby でつくる型付き Ruby
全文検索でRedmineをさらに活用!
Rubyを使った分散全文検索ミドルウェア
What's Cooking In Ruby 2.7
20090704rubyist九州
はじめてのRuby拡張ライブラリ
Couch Db勉強会0623 by yssk22
nomlab_okayamaruby_slide
Code Anything
アプリケーションへのRubyインタープリターの組み込み
社会ネットワーク分析第7回
Ad

More from Kouhei Sutou (20)

PDF
RubyKaigi 2022 - Fast data processing with Ruby and Apache Arrow
PDF
Apache Arrow Flight – ビッグデータ用高速データ転送フレームワーク #dbts2021
PDF
RubyKaigi Takeout 2021 - Red Arrow - Ruby and Apache Arrow
PDF
Apache Arrowフォーマットはなぜ速いのか
PDF
Redmine検索の未来像
PDF
Apache Arrow - A cross-language development platform for in-memory data
PDF
Better CSV processing with Ruby 2.6
PDF
Apache Arrow - データ処理ツールの次世代プラットフォーム
PDF
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
PDF
MySQL 8.0でMroonga
PDF
My way with Ruby
PDF
Mroongaの高速全文検索機能でWordPress内のコンテンツを有効活用!
PDF
MariaDBとMroongaで作る全言語対応超高速全文検索システム
PDF
PGroonga 2 – Make PostgreSQL rich full text search system backend!
PDF
PGroonga 2 - PostgreSQLでの全文検索の決定版
PDF
PostgreSQLとPGroongaで作るPHPマニュアル高速全文検索システム
PDF
Improve extension API: C++ as better language for extension
PDF
PGroonga & Zulip
PDF
MySQL・PostgreSQLだけで作る高速でリッチな全文検索システム
PDF
MySQL・PostgreSQL上で動かす全文検索エンジン「Groonga」セミナー
RubyKaigi 2022 - Fast data processing with Ruby and Apache Arrow
Apache Arrow Flight – ビッグデータ用高速データ転送フレームワーク #dbts2021
RubyKaigi Takeout 2021 - Red Arrow - Ruby and Apache Arrow
Apache Arrowフォーマットはなぜ速いのか
Redmine検索の未来像
Apache Arrow - A cross-language development platform for in-memory data
Better CSV processing with Ruby 2.6
Apache Arrow - データ処理ツールの次世代プラットフォーム
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
MySQL 8.0でMroonga
My way with Ruby
Mroongaの高速全文検索機能でWordPress内のコンテンツを有効活用!
MariaDBとMroongaで作る全言語対応超高速全文検索システム
PGroonga 2 – Make PostgreSQL rich full text search system backend!
PGroonga 2 - PostgreSQLでの全文検索の決定版
PostgreSQLとPGroongaで作るPHPマニュアル高速全文検索システム
Improve extension API: C++ as better language for extension
PGroonga & Zulip
MySQL・PostgreSQLだけで作る高速でリッチな全文検索システム
MySQL・PostgreSQL上で動かす全文検索エンジン「Groonga」セミナー

Red Data Tools

  • 1. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Data Tools 楽しく実装すればいいじゃんねー 須藤功平 株式会社クリアコード 沖縄Ruby会議02 2018-03-10
  • 2. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Data Tools プロジェクト
  • 3. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 実現したいこと Rubyで データ処理
  • 4. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 やっていること データ処理用の ツールの開発
  • 5. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 開発例 各種フォーマットを扱うgem Apache Arrow, Apache Parquet, CSV, ...✓ ✓ 各種パッケージの用意 deb, RPM, Homebrew, ...✓ ✓ ...✓
  • 6. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 この話の目的 勧誘一緒に開発しようぜ!
  • 7. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 勧誘方法 プロジェクトのポリシーを紹介 一緒に活動したくなる!✓ ✓ 開発の具体例を紹介 一緒に開発したくなる!✓ ✓
  • 8. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ポリシー1 Rubyコミュニティーを 超えて協力する もちろんRubyコミュニティーとも協力する
  • 9. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Rubyに閉じずに協力 他の言語は敵ではない 他の言語がよくなることは Rubyがなにかを失うことではない ✓ ✓ みんなよくなったらいいじゃん Rubyも他の言語も✓ ✓
  • 10. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 協力例 Apache Arrow Pythonの人達他と一緒に C/C++のライブラリーを開発 それぞれでバインディングを開発✓ それぞれで同じライブラリーを活用✓ ✓
  • 11. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ポリシー2 非難することよりも 手を動かすことが大事
  • 12. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 非難しない そんなことを している 時間はない
  • 13. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 手を動かす これ、よくないなー よくすればいいじゃんねー✓ ✓ これがないからなー 作ればいいじゃんねー✓ ✓
  • 14. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ポリシー3 一回だけの活発な活動より 小さくても 継続的に活動することが 大事
  • 15. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 一回だけの活発な活動 ○○作ったよ!どーん! すごい!✓ …数年後…今動かないんだよね…✓ ✓
  • 16. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 継続的な活動 ちまちま○○作ってるんだー! がんばってね!今後に期待!✓ …数年後…これは…使える!✓ ✓
  • 17. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 継続的な活動のために がんばり過ぎない 短距離走ではなくマラソン✓ 途中で休んだっていい✓ ✓ 1人で抱え込まない みんなでやれば途中で休みやすい✓ ✓
  • 18. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ポリシー4 現時点での知識不足は 問題ではない
  • 19. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 知識不足? 高速な実装の実現 プログラミング・数学などの 高度な知識は便利 ✓ ✓ 今すごい人でも 最初はなにも知らなかった 「今知らないこと」は 「始めない理由」にはならない ✓ ✓
  • 20. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 私たちは学べる 知識は身につく 活動していく中で自然と✓ ✓ 学び方 OSSの既存実装から学習✓ ドキュメントを読む✓ 他の人から教えてもらう✓ ✓
  • 21. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ポリシー5 部外者からの非難は 気にしない
  • 22. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 部外者からの非難 Rubyで頑張ってもアレだよねー とか 無視する✓ ✓ 対応している時間はない✓
  • 23. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ポリシー6 楽しくやろう!
  • 24. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 楽しむ 使っているのは Rubyだから!
  • 25. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ポリシー Ruby外とも協力✓ 非難するより手を動かす✓ 継続的な活動✓ 知識不足は問題ない✓ 外からの非難は気にしない✓ 楽しくやろう!✓
  • 26. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 開発例 ツールの紹介ではない✓ 実装の紹介 開発中におっと思ったやつとか✓ 紹介したいやつとか✓ ✓
  • 27. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 開発例1 csv
  • 28. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 csv CSVの読み書きライブラリー✓ 2003年から標準添付✓ 2018年からメンテナンスを引取✓
  • 29. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 digを追加したとき https://github.com/ruby/csv/pull/15 CSV::Table#dig✓ CSV::Row#dig✓
  • 30. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 digの作り方 def dig(index, *indexes) # ここだけ違う value = find_value(index) # ↓は共通 return nil if value.nil? return value if indexes.empty? value.dig(*indexes) end
  • 31. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 CSV::Rowでのfind_value row[index] # => field value digの中ではselfの[]を呼べばよい
  • 32. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 []の呼び方 def dig(index, *indexes) # インスタンスメソッドでは # selfを省略できるからこう? value = [index] # ↑は配列リテラル # ... end
  • 33. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 []の呼び方 def dig(index, *indexes) # こういうときこそsendで   # メソッド呼び出し value = send(:[], index) # 動く # ... end
  • 34. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 []の呼び方 def dig(index, *indexes) # row[index]みたいに書けば  # よかった value = self[index] # もちろん動く # ... end
  • 35. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 selfの[]の呼び方 自分も昔悩んだ気がする✓ 懐かしかったので紹介✓ みんなで開発🠊気づきやすい✓
  • 36. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 開発例2 Red Datasets
  • 37. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Datasets データを簡単に使えるように!✓ 実験・開発に便利✓
  • 38. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 例:日本語データ欲しい! require "datasets" # 日本語版Wikipediaの記事データ options = {language: :ja, type: :articles} dataset = Datasets::Wikipedia.new(options) dataset.each do |page| # 全ページを順に処理 p page.title # タイトル p page.revision.text # 本文 end # インターフェイスがeachなのがカッコいいんだよ!
  • 39. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 実装方法 データのダウンロード1. データのパース2. 順にyield3.
  • 40. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ダウンロード require "open-uri" open("https://...") do |input| File.open("...", "wb") do |output| IO.copy_stream(input, output) end end
  • 41. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 途中でエラーになったら? やり直し または 再開
  • 42. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 再開 HTTP range request
  • 43. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 HTTP range request リクエスト Range: bytes=#{start}-✓ ✓ レスポンス 206 Partial Content✓ Content-Range: bytes ...✓ ✓
  • 44. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 open-uriとrange request open-uriはrange request未対応 出力無関係のAPIだからしょうがない✓ ✓ どうなるのがいいだろう? 今度田中さんに相談しよう✓ Red Data ToolsはRubyもよくしたい ポリシー1:コミュニティーを超えて協力 ✓ ✓
  • 45. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 open-uriでrange request # 文字列キーはHTTPヘッダーになる options = {"Range" => "bytes=#{start}-"} open("...", options) do |input| # レスポンスが200か206かはわからない File.open("...", "ab") do |output| IO.copy_stream(input, output) end end
  • 46. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 大きなデータの扱い 時間がかかる✓ あとどのくらいか気になる ちゃんと動いているよね…?✓ ✓
  • 47. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 あとどのくらい? プログレスバー
  • 48. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 プログレスバーの実装 n = 40 1.upto(n) do |i| print("r|%-*s|" % [n, "*" * i]) sleep(0.1) end puts
  • 49. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 sprintfフォーマット %-*s %:フォーマット開始✓ -:左詰め✓ *:引数で幅を指定✓ s:対象は文字列✓
  • 50. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 sprintfフォーマット "%-*s" % [n, "*" * i] 幅はn桁✓ "*" * iを左詰め✓
  • 51. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 open-uriでプログレスバー length = nil progress = lambda do |current| ratio = current / length.to_f print("r|%-10s|" % ["*" * (ratio * 10).ceil]) end open(uri, content_length_proc: ->(l) {length = l}, progress_proc: progress) do |input| # ... end puts
  • 52. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 もっとプログレスバー バックグランド化したら? 表示して欲しくない ヒント:プロセスグループ ✓ ✓ リダイレクトしているときは? 表示して欲しくない ヒント:IO#tty? ✓ ✓ プログレスバーの表示幅は? ヒント:io/console/size ✓
  • 53. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 開発例3 Apache Arrow Red Arrow
  • 54. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Apache Arrow インメモリーデータ分析用 データフォーマット ほぼ固まってきた ✓ インメモリーデータ分析用 高速なデータ操作実装 徐々に実装が始まっている ✓ 今、すごくアツい!✓
  • 55. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Apache Arrowの特徴 データ交換コストが低い
  • 56. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 低データ交換コスト 複数システムで協力しやすい Rubyでデータ取得🠊Pythonで分析✓ ✓ 徐々にRubyを使えるところを 増やせる ✓
  • 57. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Apache Arrowの利用例 Scala Python Apache Spark✓ ✓ CPU GPU https://github.com/gpuopenanalytics/libgdf✓ ✓ CPU FPGA https://github.com/johanpel/fletcher✓ ✓
  • 58. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Apache ArrowをRubyでも! バインディングを本体で開発 本体の開発チームに入った✓ GObject Introspection(GI)を利用✓ ✓ GIを使うとRuby以外のバインディングも 自動生成できる ポリシー1:コミュニティーを超えて協力 ✓
  • 59. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrow Apache Arrowの Rubyバインディング ✓ GIベースのバインディングに Ruby特有の機能をプラス ✓
  • 60. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Ruby特有の機能例 スライスAPI
  • 61. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 スライス データの一部を切り出す (0..10).to_a.slice(2) # => 2 (0..10).to_a.slice(2..4) # => [2, 3, 4] (0..10).to_a.slice(2, 4) # => [2, 3, 4, 5]
  • 62. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowのスライス table.slice(2) # 2行目だけのテーブル # Array#sliceと違う
  • 63. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowのスライス table.slice(2..4) # 2,3,4行目だけのテーブル # Array#sliceと同じ
  • 64. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowのスライス table.slice(2, 4) # 2,4行目だけのテーブル # Array#sliceと違う table.slice(2, 4, 6, 8) # 2,4,6,8行目だけのテーブル # Array#sliceと違う
  • 65. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowのスライス table.slice([2, 4]) # 2,3,4,5行目だけのテーブル # Array#slice(2, 4)と同じ
  • 66. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowのスライス table.slice([true, false] * 5) # 0,2,4,6,8行目だけのテーブル
  • 67. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowのスライス table.slice do |slicer| slicer.price >= 500 end # priceカラムの値が500以上の # 行だけのテーブル
  • 68. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowのスライス table.slice do |slicer| (slicer.price >= 500) & (slicer.is_published) end # priceカラムの値が500以上かつ # is_publishedカラムの値がtrueの # 行だけのテーブル
  • 69. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowのスライス Active Recordみたいなfluent intefaceより もブロック内で式を書く方がRubyっぽいん じゃないかと思うんだよねー fluent interfaceはORを書きにくいからさー Fluent interface: http://bliki-ja.github.io/FluentInterface/
  • 70. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ブロック内で条件式 class Arrow::Table # table.slice {|slicer| ...}の実現 def slice(*slicers) if block_given? slicer = yield(Slicer.new(self)) slicers << slicer.evaluate end # ... end end
  • 71. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ブロック内で条件式 class Arrow::Slicer def initialize(table) @table = table end # slicer.priceの実現 def method_missing(name, *args, &block) ColumnCondition.new(@table[name]) end end
  • 72. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ブロック内で条件式 class ColumnCondition < Condition def initialize(column) @column = column end # slicer.price >= 500の実現 def >=(value) GreaterEqualCondition.new(@column, value) end end
  • 73. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ブロック内で条件式 class GreaterEqualCondition < Condition def initialize(column, value) @column = column @value = value end # slicer.price >= 500を評価 def evaluate # ホントはC++で実装 @column.collect {|value| value >= @value} end end
  • 74. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ブロック内で条件式 class Condition # (slicer.price >= 500) & (...)の実現 def &(condition) AndCondition.new(self, condition) end end
  • 75. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 条件式のポイント 遅延評価 各要素毎にブロックを評価✓ ブロックは一回だけ評価✓ ブロックで指定した条件は コンパイルしてC++実装で実行 ✓ ✓
  • 76. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowと外の世界 ハブになるといいかも! 各種データと変換可能に✓ 各種オブジェクトと変換可能に✓ ✓ Ruby間の連携を推進 今は互換性がないライブラリー 🠊連携できるように! ✓ ✓
  • 77. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 データ変換 Arrow::Table.load データの読み込み✓ ✓ Arrow::Table#save データの書き出し✓ ✓
  • 78. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 データ変換例 # CSVを読み込んで table = Arrow::Table.load("a.csv") # Arrowで保存 table.save("a.arrow") # Parquetで保存 table.save("a.parquet")
  • 79. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 CSVの読み込み CSVは広く使われている CSVなデータを簡単に使えると捗る✓ ✓ 難しいところ データ定義が緩い 例:カラムの型情報がない ✓ ✓
  • 80. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowでの読み込み 2パスで処理 全部処理して各カラムの型を推定a. 推定した型でArrowのデータに変換b. ✓ 時間がかかる 読み込んだデータを別の形式に変換して再利用す る使い方を想定 だから、まぁ、いいかなぁって ✓ ✓
  • 81. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 型の推定 candidate = nil column.each do |value| case value when nil; next # ignore when "true", "false", true, false; c = :boolean when Integer; c = :integer # ... else; c = :string # わからなかったら文字列 end candidate ||= c candidate = :string if candidate != c # 混ざったら文字列 break if candidate == :string # 文字列なら終わり end candidate || :string # わからなかったら文字列
  • 82. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 オブジェクト変換 Numo::NArray, NMatrix 既存の多次元配列オブジェクト✓ ✓ PyCall経由でPyArrow Rubyでデータ作成🠊Pythonで処理✓ ✓ GDK Pixbuf 画像オブジェクト✓ ✓
  • 83. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 オブジェクト変換例1 # PNG画像を読み込み pixbuf = GdkPixbuf::Pixbuf.new(file: "a.png") # Arrow経由でNumo::NArrayに変換 narray = pixbuf.to_arrow.to_narray # 不透明に(アルファ値(透明度)を0xffに) narray[true, true, 3] = 0xff # Arrow経由でGdkPixbuf::Pixbufに変換 no_alpha_pixbuf = narray.to_arrow.to_pixbuf # GIF画像として保存 no_alpha_pixbuf.save(filename: "a-no-alpha.gif")
  • 84. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Pixbuf→Arrow class GdkPixbuf::Pixbuf def to_arrow bytes = read_pixel_bytes # ピクセル値 buffer = Arrow::Buffer.new(bytes) # 高さ、幅、チャンネル数の3次元配列 # チャンネル数:RGBAだと4チャンネル shape = [height, width, n_channels] # バイト列なのでUInt8 Arrow::Tensor.new(Arrow::UInt8DataType.new, buffer, shape) end end
  • 85. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 ゼロコピーの実現 ゼロコピー 同じメモリー領域を参照し、 コピーせずに同じデータを利用 ✓ 速い!!!✓ ✓ データ バイト列へのポインター✓ RubyではRSTRING_PTR(string)✓ ✓
  • 86. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Stringとゼロコピー /* pointerの内容をコピー */ rb_str_new(pointer, size); /* pointerの内容を参照:ゼロコピー */ rb_str_new_static(pointer, size);
  • 87. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 StringとゼロコピーとGC arrow_data = /* ... */; /* ゼロコピー */ rb_str_new_static(arrow_data, size); /* arrow_dataはいつ、だれが開放? */
  • 88. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Rubyでゼロコピー rb_str_new_static()だけ メモリー管理できない✓ ✓ メモリー管理する何かが必要✓
  • 89. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Arrowでゼロコピー GBytesを利用✓ GBytes GLib提供のバイト列オブジェクト✓ リファレンスカウントあり✓ ✓ RubyだとGLib::Bytes✓
  • 90. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 GLib::Bytes#to_s static VALUE rgbytes_to_s(VALUE self) { GBytes *bytes = RVAL2BOXED(self, G_TYPE_BYTES); gsize size; gconstpointer data = g_bytes_get_data(bytes, &size); /* ゼロコピーでASCII-8BITな文字列を生成 */ VALUE rb_data = rb_enc_str_new_static( data, size, rb_ascii8bit_encoding()); rb_iv_set(rb_data, "@bytes", self); /* GC対策 */ return rb_data; }
  • 91. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 GLib::Bytes#initialize static VALUE rgbytes_initialize(VALUE self, VALUE rb_data) { const char *pointer = RSTRING_PTR(rb_data); long size = RSTRING_LEN(rb_data); GBytes *bytes; if (RB_OBJ_FROZEN(rb_data)) { /* ゼロコピー */ bytes = g_bytes_new_static(pointer, size); rb_iv_set(self, "source", rb_data); /* GC対策 */ } else { /* コピー */ bytes = g_bytes_new(pointer, size); } G_INITIALIZE(self, bytes); return Qnil; }
  • 92. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 GBytesはすでに使っていた class GdkPixbuf::Pixbuf def to_arrow # ピクセル値はGLib::Bytes bytes = read_pixel_bytes buffer = Arrow::Buffer.new(bytes) shape = [height, width, n_channels] Arrow::Tensor.new(Arrow::UInt8DataType.new, buffer, shape) end end
  • 93. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 オブジェクト変換例2 # RelationをArrow形式に users = User .where("age >= ?", 20) .to_arrow
  • 94. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Relation→Arrow module ArrowActiveRecord::Arrowable def to_arrow(batch_size: 10000) in_batches(of: batch_size).each do |relation| column_values_set = relation.pluck(*column_names).transpose data_types.each_with_index do |data_type, i| column_values = column_values_set[i] arrow_batches[i] << build_arrow_array(column_values, data_type) end end # ... Arrow::Table.new(...) end end
  • 95. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Chainer ChainerのRuby移植
  • 96. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Chainer 深層学習フレームワーク Pythonのみで実装✓ ✓ 移植しやすい Pythonのみで実装されているから✓ ✓
  • 97. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Red Chainerサンプル model = Chainer::Links::Model::Classifier.new(MLP.new(args[:unit], 10)) optimizer = Chainer::Optimizers::Adam.new optimizer.setup(model) train, test = Chainer::Datasets::Mnist.get_mnist train_iter = Chainer::Iterators::SerialIterator.new(train, args[:batchsize]) test_iter = Chainer::Iterators::SerialIterator.new(test, args[:batchsize], repeat: false, shuffle: false) # ... 横に長い
  • 98. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Chainerのサンプル import chainer import chainer.links as L model = L.Classifier(MLP(args.unit, 10)) optimizer = chainer.optimizers.Adam() optimizer.setup(model) train, test = chainer.datasets.get_mnist() train_iter = chainer.iterators.SerialIterator(train, args.batchsize) test_iter = chainer.iterators.SerialIterator(test, args.batchsize, repeat=False, shuffle=False) こっちも横に長い
  • 99. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Pythonでの短く仕方 # 通常 import chainer model = chainer.links.Classifier(MLP(args.unit, 10)) # Lでショートカット import chainer.links as L model = L.Classifier(MLP(args.unit, 10))
  • 100. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Rubyでの短く仕方 # 通常 model = Chainer::Links::Model::Classifier.new(...) # Lでショートカット L = Chainer::Links model = L::Model::Classifier.new(...)
  • 101. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 PythonとRubyの違い Python ファイル内でだけLが有効✓ ファイル単位でネームスペース✓ ✓ Ruby グローバルにLが有効✓ 微妙!✓ ✓
  • 102. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Rubyらしく短く # Rubyのネームスペースの仕組みはモジュール Module.new do include Chainer::Links model = Model::Classifier.new(...) end
  • 103. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 開発したくなった? 楽しそう! 一緒に開発しようぜ!✓ ✓ やっぱRubyでデータ扱いたい! 一緒に開発しようぜ!✓ ✓ レベルアップしたい! 一緒に開発しようぜ!✓ ✓
  • 104. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 レベルアップへの道 NG集をたくさん覚える✓ よいコードにたくさん触れる✓
  • 105. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 よいコード Red Data Toolsに たくさんある!
  • 106. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 一緒に開発 どこからでもオンラインで GitHubとGitter(チャット)を使用✓ ✓ 東京は月一オフラインで 「OSS Gate Red Data Tools」✓ ✓
  • 107. Red Data Tools - 楽しく実装すればいいじゃんねー Powered by Rabbit 2.2.2 Join Red Data Tools! Webサイト https://red-data-tools.github.io/ja/✓ ✓ Gitter(チャット) https://gitter.im/red-data-tools/ja✓ ✓ GitHub https://github.com/red-data-tools/✓ ✓