torch-rb 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +23 -41
- data/codegen/generate_functions.rb +46 -8
- data/codegen/native_functions.yaml +1103 -373
- data/ext/torch/backends.cpp +17 -0
- data/ext/torch/ext.cpp +8 -0
- data/ext/torch/fft.cpp +13 -0
- data/ext/torch/fft_functions.h +6 -0
- data/ext/torch/linalg.cpp +13 -0
- data/ext/torch/linalg_functions.h +6 -0
- data/ext/torch/ruby_arg_parser.h +17 -3
- data/ext/torch/special.cpp +13 -0
- data/ext/torch/special_functions.h +6 -0
- data/ext/torch/templates.h +0 -37
- data/ext/torch/tensor.cpp +8 -8
- data/lib/torch/nn/convnd.rb +2 -0
- data/lib/torch/nn/functional_attention.rb +241 -0
- data/lib/torch/nn/module.rb +30 -0
- data/lib/torch/nn/module_list.rb +49 -0
- data/lib/torch/nn/multihead_attention.rb +123 -0
- data/lib/torch/nn/parameter.rb +6 -0
- data/lib/torch/nn/transformer.rb +92 -0
- data/lib/torch/nn/transformer_decoder.rb +25 -0
- data/lib/torch/nn/transformer_decoder_layer.rb +43 -0
- data/lib/torch/nn/transformer_encoder.rb +25 -0
- data/lib/torch/nn/transformer_encoder_layer.rb +36 -0
- data/lib/torch/nn/utils.rb +12 -0
- data/lib/torch/tensor.rb +20 -0
- data/lib/torch/utils/data/data_loader.rb +2 -0
- data/lib/torch/version.rb +1 -1
- data/lib/torch.rb +6 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09221364dad232f1b76129fe9dc9407675cc2afbd03bd1339c736d4eec752df7'
|
4
|
+
data.tar.gz: a37a0584aed809009ebd74e7c0da9430481ccabf1ac915d2468ee7511c249588
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c220d35971b9ce3e5a7a80f6a5d1ae4324f3524d0e0171c680deced66fe2f29342a46eecb1a4447d84a401a677c7bb1ef910a0c7ee6c925ea4b578b7e5712772
|
7
|
+
data.tar.gz: 807fe2907de1caac92da6dddb0154b7971dda3aa0ee2c53f6b3046732f4bf3c02310e59a6441efa0fdf1ad3d0ddb5dcd7a3c1a946adbfbea73b6b30f10a71487
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
## 0.9.0 (2021-10-23)
|
2
|
+
|
3
|
+
- Updated LibTorch to 1.10.0
|
4
|
+
- Added `real` and `imag` methods to tensors
|
5
|
+
|
6
|
+
## 0.8.3 (2021-10-17)
|
7
|
+
|
8
|
+
- Fixed `dup` method for tensors and parameters
|
9
|
+
- Fixed issues with transformers
|
10
|
+
|
11
|
+
## 0.8.2 (2021-10-03)
|
12
|
+
|
13
|
+
- Added transformers
|
14
|
+
- Added left shift and right shift
|
15
|
+
|
16
|
+
## 0.8.1 (2021-06-15)
|
17
|
+
|
18
|
+
- Added `Backends` module
|
19
|
+
- Added `FFT` module
|
20
|
+
- Added `Linalg` module
|
21
|
+
- Added `Special` module
|
22
|
+
|
1
23
|
## 0.8.0 (2021-06-15)
|
2
24
|
|
3
25
|
- Updated LibTorch to 1.9.0
|
data/README.md
CHANGED
@@ -28,15 +28,19 @@ It can take a few minutes to compile the extension.
|
|
28
28
|
|
29
29
|
## Getting Started
|
30
30
|
|
31
|
-
|
31
|
+
A good place to start is [Deep Learning with Torch.rb: A 60 Minute Blitz](tutorials/blitz/README.md).
|
32
32
|
|
33
|
-
|
33
|
+
## Tutorials
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
- [Transfer learning](tutorials/transfer_learning/README.md)
|
36
|
+
- [Sequence models](tutorials/nlp/sequence_models.md)
|
37
|
+
- [Word embeddings](tutorials/nlp/word_embeddings.md)
|
38
38
|
|
39
|
-
|
39
|
+
## Examples
|
40
|
+
|
41
|
+
- [Image classification with MNIST](examples/mnist) ([日本語版](https://qiita.com/kojix2/items/c19c36dc1bf73ea93409))
|
42
|
+
- [Collaborative filtering with MovieLens](examples/movielens)
|
43
|
+
- [Generative adversarial networks](examples/gan)
|
40
44
|
|
41
45
|
## API
|
42
46
|
|
@@ -48,7 +52,7 @@ This library follows the [PyTorch API](https://pytorch.org/docs/stable/torch.htm
|
|
48
52
|
|
49
53
|
You can follow PyTorch tutorials and convert the code to Ruby in many cases. Feel free to open an issue if you run into problems.
|
50
54
|
|
51
|
-
##
|
55
|
+
## Overview
|
52
56
|
|
53
57
|
Some examples below are from [Deep Learning with PyTorch: A 60 Minutes Blitz](https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html)
|
54
58
|
|
@@ -214,7 +218,7 @@ Define a neural network
|
|
214
218
|
```ruby
|
215
219
|
class MyNet < Torch::NN::Module
|
216
220
|
def initialize
|
217
|
-
super
|
221
|
+
super()
|
218
222
|
@conv1 = Torch::NN::Conv2d.new(1, 6, 3)
|
219
223
|
@conv2 = Torch::NN::Conv2d.new(6, 16, 3)
|
220
224
|
@fc1 = Torch::NN::Linear.new(16 * 6 * 6, 120)
|
@@ -225,20 +229,10 @@ class MyNet < Torch::NN::Module
|
|
225
229
|
def forward(x)
|
226
230
|
x = Torch::NN::F.max_pool2d(Torch::NN::F.relu(@conv1.call(x)), [2, 2])
|
227
231
|
x = Torch::NN::F.max_pool2d(Torch::NN::F.relu(@conv2.call(x)), 2)
|
228
|
-
x =
|
232
|
+
x = Torch.flatten(x, 1)
|
229
233
|
x = Torch::NN::F.relu(@fc1.call(x))
|
230
234
|
x = Torch::NN::F.relu(@fc2.call(x))
|
231
|
-
|
232
|
-
x
|
233
|
-
end
|
234
|
-
|
235
|
-
def num_flat_features(x)
|
236
|
-
size = x.size[1..-1]
|
237
|
-
num_features = 1
|
238
|
-
size.each do |s|
|
239
|
-
num_features *= s
|
240
|
-
end
|
241
|
-
num_features
|
235
|
+
@fc3.call(x)
|
242
236
|
end
|
243
237
|
end
|
244
238
|
```
|
@@ -402,19 +396,9 @@ Here’s a list of functions to create tensors (descriptions from the [C++ docs]
|
|
402
396
|
Torch.zeros(3) # tensor([0, 0, 0])
|
403
397
|
```
|
404
398
|
|
405
|
-
## Examples
|
406
|
-
|
407
|
-
Here are a few full examples:
|
408
|
-
|
409
|
-
- [Image classification with MNIST](examples/mnist) ([日本語版](https://qiita.com/kojix2/items/c19c36dc1bf73ea93409))
|
410
|
-
- [Collaborative filtering with MovieLens](examples/movielens)
|
411
|
-
- [Sequence models and word embeddings](examples/nlp)
|
412
|
-
- [Generative adversarial networks](examples/gan)
|
413
|
-
- [Transfer learning](examples/transfer-learning)
|
414
|
-
|
415
399
|
## LibTorch Installation
|
416
400
|
|
417
|
-
[Download LibTorch](https://pytorch.org/)
|
401
|
+
[Download LibTorch](https://pytorch.org/) (for Linux, use the `cxx11 ABI` version). Then run:
|
418
402
|
|
419
403
|
```sh
|
420
404
|
bundle config build.torch-rb --with-torch-dir=/path/to/libtorch
|
@@ -424,7 +408,8 @@ Here’s the list of compatible versions.
|
|
424
408
|
|
425
409
|
Torch.rb | LibTorch
|
426
410
|
--- | ---
|
427
|
-
0.
|
411
|
+
0.9.0+ | 1.10.0+
|
412
|
+
0.8.0-0.8.3 | 1.9.0-1.9.1
|
428
413
|
0.6.0-0.7.0 | 1.8.0-1.8.1
|
429
414
|
0.5.0-0.5.3 | 1.7.0-1.7.1
|
430
415
|
0.3.0-0.4.2 | 1.6.0
|
@@ -444,9 +429,7 @@ Then install the gem (no need for `bundle config`).
|
|
444
429
|
|
445
430
|
## Performance
|
446
431
|
|
447
|
-
|
448
|
-
|
449
|
-
Deep learning is significantly faster on a GPU. Install [CUDA](https://developer.nvidia.com/cuda-downloads) and [cuDNN](https://developer.nvidia.com/cudnn) and reinstall the gem.
|
432
|
+
Deep learning is significantly faster on a GPU. With Linux, install [CUDA](https://developer.nvidia.com/cuda-downloads) and [cuDNN](https://developer.nvidia.com/cudnn) and reinstall the gem.
|
450
433
|
|
451
434
|
Check if CUDA is available
|
452
435
|
|
@@ -460,15 +443,14 @@ Move a neural network to a GPU
|
|
460
443
|
net.cuda
|
461
444
|
```
|
462
445
|
|
463
|
-
|
446
|
+
If you don’t have a GPU that supports CUDA, we recommend using a cloud service. [Paperspace](https://www.paperspace.com/) has a great free plan. We’ve put together a [Docker image](https://github.com/ankane/ml-stack) to make it easy to get started. On Paperspace, create a notebook with a custom container. Under advanced options, set the container name to:
|
464
447
|
|
465
|
-
|
466
|
-
|
467
|
-
```sh
|
468
|
-
brew upgrade ruby-build
|
469
|
-
rbenv install [version]
|
448
|
+
```text
|
449
|
+
ankane/ml-stack:torch-gpu
|
470
450
|
```
|
471
451
|
|
452
|
+
And leave the other fields in that section blank. Once the notebook is running, you can run the [MNIST example](https://github.com/ankane/ml-stack/blob/master/torch-gpu/MNIST.ipynb).
|
453
|
+
|
472
454
|
## History
|
473
455
|
|
474
456
|
View the [changelog](https://github.com/ankane/torch.rb/blob/master/CHANGELOG.md)
|
@@ -11,6 +11,9 @@ def generate_functions
|
|
11
11
|
generate_files("torch", :define_singleton_method, functions[:torch])
|
12
12
|
generate_files("tensor", :define_method, functions[:tensor])
|
13
13
|
generate_files("nn", :define_singleton_method, functions[:nn])
|
14
|
+
generate_files("fft", :define_singleton_method, functions[:fft])
|
15
|
+
generate_files("linalg", :define_singleton_method, functions[:linalg])
|
16
|
+
generate_files("special", :define_singleton_method, functions[:special])
|
14
17
|
end
|
15
18
|
|
16
19
|
def load_functions
|
@@ -20,11 +23,14 @@ end
|
|
20
23
|
|
21
24
|
def skip_functions(functions)
|
22
25
|
functions.reject do |f|
|
23
|
-
f.base_name.start_with?("_") ||
|
26
|
+
(f.base_name.start_with?("_") && f.base_name != "__lshift__" && f.base_name != "__rshift__") ||
|
24
27
|
f.base_name.include?("_backward") ||
|
25
28
|
f.base_name.include?("_forward") ||
|
26
29
|
f.base_name == "to" ||
|
27
30
|
f.base_name == "record_stream" ||
|
31
|
+
f.base_name == "is_pinned" ||
|
32
|
+
f.base_name == "pin_memory" ||
|
33
|
+
f.base_name == "fused_moving_avg_obs_fake_quant" ||
|
28
34
|
# in ext.cpp
|
29
35
|
f.base_name == "index" ||
|
30
36
|
f.base_name == "index_put_" ||
|
@@ -38,10 +44,26 @@ end
|
|
38
44
|
|
39
45
|
def group_functions(functions)
|
40
46
|
nn_functions, other_functions = functions.partition { |f| f.python_module == "nn" }
|
47
|
+
linalg_functions, other_functions = other_functions.partition { |f| f.python_module == "linalg" }
|
48
|
+
fft_functions, other_functions = other_functions.partition { |f| f.python_module == "fft" }
|
49
|
+
special_functions, other_functions = other_functions.partition { |f| f.python_module == "special" }
|
50
|
+
unexpected_functions, other_functions = other_functions.partition { |f| f.python_module }
|
41
51
|
torch_functions = other_functions.select { |f| f.variants.include?("function") }
|
42
52
|
tensor_functions = other_functions.select { |f| f.variants.include?("method") }
|
43
53
|
|
44
|
-
|
54
|
+
if unexpected_functions.any?
|
55
|
+
unexpected_modules = unexpected_functions.map(&:python_module).uniq
|
56
|
+
raise "Unexpected modules: #{unexpected_modules.join(", ")}"
|
57
|
+
end
|
58
|
+
|
59
|
+
{
|
60
|
+
torch: torch_functions,
|
61
|
+
tensor: tensor_functions,
|
62
|
+
nn: nn_functions,
|
63
|
+
linalg: linalg_functions,
|
64
|
+
fft: fft_functions,
|
65
|
+
special: special_functions
|
66
|
+
}
|
45
67
|
end
|
46
68
|
|
47
69
|
def generate_files(type, def_method, functions)
|
@@ -111,11 +133,15 @@ def generate_attach_def(name, type, def_method)
|
|
111
133
|
end
|
112
134
|
|
113
135
|
ruby_name = "_#{ruby_name}" if ["size", "stride", "random!", "stft"].include?(ruby_name)
|
136
|
+
ruby_name = ruby_name.sub(/\Afft_/, "") if type == "fft"
|
137
|
+
ruby_name = ruby_name.sub(/\Alinalg_/, "") if type == "linalg"
|
138
|
+
ruby_name = ruby_name.sub(/\Aspecial_/, "") if type == "special"
|
139
|
+
ruby_name = name if name.start_with?("__")
|
114
140
|
|
115
141
|
# cast for Ruby < 2.7 https://github.com/thisMagpie/fftw/issues/22#issuecomment-49508900
|
116
142
|
cast = RUBY_VERSION.to_f > 2.7 ? "" : "(VALUE (*)(...)) "
|
117
143
|
|
118
|
-
"rb_#{def_method}(m, \"#{ruby_name}\", #{cast}#{type}
|
144
|
+
"rb_#{def_method}(m, \"#{ruby_name}\", #{cast}#{full_name(name, type)}, -1);"
|
119
145
|
end
|
120
146
|
|
121
147
|
def generate_method_def(name, functions, type, def_method)
|
@@ -128,7 +154,7 @@ def generate_method_def(name, functions, type, def_method)
|
|
128
154
|
|
129
155
|
template = <<~EOS
|
130
156
|
// #{name}
|
131
|
-
static VALUE #{type}
|
157
|
+
static VALUE #{full_name(name, type)}(int argc, VALUE* argv, VALUE self_)
|
132
158
|
{
|
133
159
|
HANDLE_TH_ERRORS#{assign_self}
|
134
160
|
static RubyArgParser parser({
|
@@ -364,6 +390,8 @@ def generate_function_params(function, params, remove_self)
|
|
364
390
|
end
|
365
391
|
when "generator", "tensorlist", "intlist"
|
366
392
|
func
|
393
|
+
when "string"
|
394
|
+
"stringViewOptional"
|
367
395
|
else
|
368
396
|
"#{func}Optional"
|
369
397
|
end
|
@@ -401,9 +429,7 @@ def generate_dispatch_params(function, params)
|
|
401
429
|
if function.out?
|
402
430
|
"const Tensor &"
|
403
431
|
else
|
404
|
-
|
405
|
-
# "const c10::optional<at::Tensor> &"
|
406
|
-
"const OptionalTensor &"
|
432
|
+
"const c10::optional<at::Tensor> &"
|
407
433
|
end
|
408
434
|
elsif param[:modifier]
|
409
435
|
if param[:modifier].include?("!") && function.retvals.size > 1
|
@@ -427,7 +453,11 @@ def generate_dispatch_params(function, params)
|
|
427
453
|
when "float[]"
|
428
454
|
"ArrayRef<double>"
|
429
455
|
when "str"
|
430
|
-
|
456
|
+
if param[:optional]
|
457
|
+
"c10::string_view"
|
458
|
+
else
|
459
|
+
"std::string"
|
460
|
+
end
|
431
461
|
when "Scalar", "bool", "ScalarType", "Layout", "Device", "Storage", "Generator", "MemoryFormat", "Storage"
|
432
462
|
param[:type]
|
433
463
|
else
|
@@ -560,3 +590,11 @@ def signature_type(param)
|
|
560
590
|
type += "?" if param[:optional]
|
561
591
|
type
|
562
592
|
end
|
593
|
+
|
594
|
+
def full_name(name, type)
|
595
|
+
if %w(fft linalg special).include?(type) && name.start_with?("#{type}_")
|
596
|
+
name
|
597
|
+
else
|
598
|
+
"#{type}_#{name}"
|
599
|
+
end
|
600
|
+
end
|