tensorflow 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eace7d05756f006a0710499d67eeb878234a5c67fafb877aa5e154f7f58a0b0b
4
- data.tar.gz: 87f168e411872d952562550b6dfd73ed902c989b5d54df241198732f7a518ae5
3
+ metadata.gz: 1be807c9cecb0736fd171d31c9144d265f66ba677f9b045bf4e1d8245eb7c330
4
+ data.tar.gz: eef070cae5c973b546af0658a75bd8954a87f5db5a30be9114e5317ac5508f17
5
5
  SHA512:
6
- metadata.gz: cc67f8f76b77adc109f85c86aba641e71e6a52f60f7de9a0c983af9bd8a1ada5dc989ebfc8ae40b75da2957d24c07716385d6d949d1df7dc5fd88d4e7bb1172c
7
- data.tar.gz: 545a0fb338134f3cd1088d6467cbaa3ebba2465a845bdb91ada369cbc594f5e63108d20a6d6d5e4884885a42b915483fce8414e0ae1ec27b0833b9861a176fe1
6
+ metadata.gz: 428d8e228de1cdd6f17ac0592b522c2b28fc7cfd7e5007d141c96bd16f1471cdf2fa1be559e44a696247e0454cab8bcf6ab36bab1b45d215f3c1158a1e23b1ca
7
+ data.tar.gz: 3e91f6daa182a8aa270192e581b1f86755d80ea257e625fbd0678c9a60584e3662666af3b9b55608ecb65fca7162df84d324ce9b3d954bf08c094be1cdf474e2
data/CHANGELOG.md CHANGED
@@ -1,16 +1,23 @@
1
- ## 0.1.2
1
+ ## 0.2.0 (2021-07-07)
2
+
3
+ - Added support for TensorFlow 2.5
4
+ - Dropped support for TensorFlow < 2.5
5
+ - Dropped support for Ruby < 2.6
6
+ - Changed to Apache 2.0 license to match TensorFlow
7
+
8
+ ## 0.1.2 (2019-09-24)
2
9
 
3
10
  - Added `Audio`, `Bitwise`, `Image`, `IO`, `Linalg`, `NN`, `Strings`, and `Data::Dataset` modules
4
11
  - Added `numo` method to tensors
5
12
  - Added Boston housing dataset
6
13
  - Fixed string encoding
7
14
 
8
- ## 0.1.1
15
+ ## 0.1.1 (2019-09-20)
9
16
 
10
17
  - Added `Math` and `RawOps` modules
11
18
  - Added support for more data types
12
19
  - Added MNIST dataset
13
20
 
14
- ## 0.1.0
21
+ ## 0.1.0 (2019-09-17)
15
22
 
16
23
  - First release
data/LICENSE.txt CHANGED
@@ -1,22 +1,202 @@
1
- Copyright (c) 2019 Andrew Kane
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
data/NOTICE.txt ADDED
@@ -0,0 +1,14 @@
1
+ Copyright 2019-2021 The TensorFlow Authors
2
+ Copyright 2019-2021 Andrew Kane
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # TensorFlow
2
2
 
3
- [TensorFlow](https://github.com/tensorflow/tensorflow) - the end-to-end machine learning platform - for Ruby
3
+ :fire: [TensorFlow](https://github.com/tensorflow/tensorflow) - the end-to-end machine learning platform - for Ruby
4
4
 
5
- :fire: Uses the C API under the hood
5
+ This gem is currently experimental and only supports basic tensor operations at the moment. Check out [Torch.rb](https://github.com/ankane/torch-rb) for a more complete deep learning library.
6
6
 
7
- [![Build Status](https://travis-ci.org/ankane/tensorflow.svg?branch=master)](https://travis-ci.org/ankane/tensorflow)
7
+ To run a TensorFlow model in Ruby, [convert it to ONNX](https://github.com/onnx/tensorflow-onnx) and use [ONNX Runtime](https://github.com/ankane/onnxruntime). Check out [this tutorial](https://ankane.org/tensorflow-ruby) for a full example.
8
+
9
+ [![Build Status](https://github.com/ankane/tensorflow/workflows/build/badge.svg?branch=master)](https://github.com/ankane/tensorflow/actions)
8
10
 
9
11
  ## Installation
10
12
 
@@ -22,13 +24,13 @@ gem 'tensorflow'
22
24
 
23
25
  ## Getting Started
24
26
 
25
- This library follows the TensorFlow 2.0 [Python API](https://www.tensorflow.org/versions/r2.0/api_docs/python/tf). Many methods and options are missing at the moment. Here’s the [current plan](https://github.com/ankane/tensorflow/issues/1). Additional PRs welcome!
27
+ This library follows the TensorFlow 2 [Python API](https://www.tensorflow.org/api_docs/python/tf). Many methods and options are missing at the moment. Here’s the [current plan](https://github.com/ankane/tensorflow/issues/1). Additional PRs welcome!
26
28
 
27
29
  ## Constants
28
30
 
29
31
  ```ruby
30
- a = Tf.constant(2)
31
- b = Tf.constant(3)
32
+ a = Tf.constant([1, 2, 3])
33
+ b = Tf.constant([4, 5, 6])
32
34
  a + b
33
35
  ```
34
36
 
@@ -42,8 +44,8 @@ w = v + 1
42
44
  ## Math
43
45
 
44
46
  ```ruby
45
- Tf::Math.abs(-2)
46
- Tf::Math.sqrt(4)
47
+ Tf::Math.abs([-1, -2])
48
+ Tf::Math.sqrt([1.0, 4.0, 9.0])
47
49
  ```
48
50
 
49
51
  ## FizzBuzz
@@ -137,11 +139,11 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
137
139
  - Write, clarify, or fix documentation
138
140
  - Suggest or add new features
139
141
 
140
- To get started with development and testing:
142
+ To get started with development:
141
143
 
142
144
  ```sh
143
145
  git clone https://github.com/ankane/tensorflow.git
144
146
  cd tensorflow
145
147
  bundle install
146
- rake test
148
+ bundle exec rake test
147
149
  ```
data/lib/tensorflow.rb CHANGED
@@ -43,11 +43,18 @@ require "tensorflow/keras/datasets/fashion_mnist"
43
43
  require "tensorflow/keras/datasets/imdb"
44
44
  require "tensorflow/keras/datasets/mnist"
45
45
  require "tensorflow/keras/datasets/reuters"
46
+ require "tensorflow/keras/layers/conv"
47
+ require "tensorflow/keras/layers/conv2d"
46
48
  require "tensorflow/keras/layers/dense"
47
49
  require "tensorflow/keras/layers/dropout"
48
50
  require "tensorflow/keras/layers/flatten"
51
+ require "tensorflow/keras/losses/sparse_categorical_crossentropy"
49
52
  require "tensorflow/keras/metrics/mean"
53
+ require "tensorflow/keras/metrics/sparse_categorical_accuracy"
54
+ require "tensorflow/keras/model"
50
55
  require "tensorflow/keras/models/sequential"
56
+ require "tensorflow/keras/optimizers/adam"
57
+ require "tensorflow/keras/preprocessing/image"
51
58
  require "tensorflow/keras/utils"
52
59
 
53
60
  module TensorFlow
@@ -80,6 +87,9 @@ module TensorFlow
80
87
 
81
88
  def convert_to_tensor(value, dtype: nil)
82
89
  value = Tensor.new(value, dtype: dtype) unless value.is_a?(Tensor)
90
+ if dtype && value.dtype != dtype
91
+ raise Error, "Tensor conversion requested dtype #{dtype} for Tensor with dtype #{value.dtype}"
92
+ end
83
93
  value
84
94
  end
85
95
  end
@@ -9,6 +9,30 @@ module TensorFlow
9
9
  FFI.TFE_DeleteContextOptions(options)
10
10
  end
11
11
 
12
+ def function?(name)
13
+ FFI.TFE_ContextHasFunction(@pointer, name) != 0
14
+ end
15
+
16
+ def device_policy
17
+ FFI::ContextDevicePlacementPolicy[FFI.TFE_ContextGetDevicePlacementPolicy(@pointer)]
18
+ end
19
+
20
+ def enable_run_metadata
21
+ FFI.TFE_ContextEnableRunMetadata(@pointer)
22
+ end
23
+
24
+ def disable_run_metadata
25
+ FFI.TFE_ContextDisableRunMetadata(@pointer)
26
+ end
27
+
28
+ def start_step
29
+ FFI.TFE_ContextStartStep(@pointer)
30
+ end
31
+
32
+ def end_step
33
+ FFI.TFE_ContextEndStep(@pointer)
34
+ end
35
+
12
36
  def self.finalize(pointer)
13
37
  # must use proc instead of stabby lambda
14
38
  proc { FFI.TFE_DeleteContext(pointer) }
@@ -36,11 +36,16 @@ module TensorFlow
36
36
  attach_function :TF_DeleteTensor, %i[pointer], :void
37
37
  attach_function :TF_TensorData, %i[pointer], :pointer
38
38
  attach_function :TF_TensorByteSize, %i[pointer], :size_t
39
- attach_function :TF_StringEncode, %i[pointer size_t pointer size_t pointer], :size_t
40
- attach_function :TF_StringDecode, %i[pointer size_t pointer pointer pointer], :size_t
41
- attach_function :TF_StringEncodedSize, %i[size_t], :size_t
39
+
40
+ # https://github.com/tensorflow/tensorflow/blob/master/tensorflow/c/tf_tstring.h
41
+ attach_function :TF_StringInit, %i[pointer], :void
42
+ attach_function :TF_StringCopy, %i[pointer pointer size_t], :void
43
+ attach_function :TF_StringGetDataPointer, %i[pointer], :string
44
+ attach_function :TF_StringGetSize, %i[pointer], :size_t
42
45
 
43
46
  # https://github.com/tensorflow/tensorflow/blob/master/tensorflow/c/eager/c_api.h
47
+ ContextDevicePlacementPolicy = enum(:explicit, :warn, :silent, :silent_for_int32)
48
+
44
49
  attach_function :TFE_NewContextOptions, %i[], :pointer
45
50
  attach_function :TFE_ContextOptionsSetAsync, %i[pointer char], :void
46
51
  attach_function :TFE_DeleteContextOptions, %i[pointer], :void
@@ -75,5 +80,10 @@ module TensorFlow
75
80
  attach_function :TFE_OpSetAttrTypeList, %i[pointer string pointer int], :void
76
81
  attach_function :TFE_OpSetAttrShapeList, %i[pointer string pointer pointer int pointer], :void
77
82
  attach_function :TFE_Execute, %i[pointer pointer pointer pointer], :pointer
83
+ attach_function :TFE_ContextHasFunction, %i[pointer string], :uchar
84
+ attach_function :TFE_ContextEnableRunMetadata, %i[pointer], :void
85
+ attach_function :TFE_ContextDisableRunMetadata, %i[pointer], :void
86
+ attach_function :TFE_ContextStartStep, %i[pointer], :void
87
+ attach_function :TFE_ContextEndStep, %i[pointer], :void
78
88
  end
79
89
  end
@@ -0,0 +1,14 @@
1
+ module TensorFlow
2
+ module Keras
3
+ module Layers
4
+ class Conv
5
+ def initialize(rank, filters, kernel_size, activation: nil)
6
+ @rank = rank
7
+ @filter = filters
8
+ @kernel_size = kernel_size
9
+ @activation = activation
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module TensorFlow
2
+ module Keras
3
+ module Layers
4
+ class Conv2D < Conv
5
+ def initialize(filters, kernel_size, activation: nil)
6
+ super(2, filters, kernel_size, activation: activation)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -2,7 +2,65 @@ module TensorFlow
2
2
  module Keras
3
3
  module Layers
4
4
  class Dense
5
- def initialize(units, activation: nil)
5
+ def initialize(units, activation: nil, use_bias: true, kernel_initializer: "glorot_uniform", bias_initializer: "zeros", dtype: :float)
6
+ @units = units
7
+ @activation = activation
8
+ @use_bias = use_bias
9
+ @kernel_initializer = kernel_initializer
10
+ @bias_initializer = bias_initializer
11
+ @dtype = dtype
12
+ @built = false
13
+ end
14
+
15
+ def build(input_shape)
16
+ last_dim = input_shape.last
17
+ @kernel = Utils.add_weight(name: "kernel", shape: [last_dim, @units], initializer: @kernel_initializer, dtype: @dtype)
18
+
19
+ if @use_bias
20
+ @bias = Utils.add_weight(name: "bias", shape: [@units], initializer: @bias_initializer, dtype: @dtype)
21
+ else
22
+ @bias = nil
23
+ end
24
+
25
+ @output_shape = [last_dim, @units]
26
+
27
+ @built = true
28
+ end
29
+
30
+ def output_shape
31
+ @output_shape
32
+ end
33
+
34
+ def count_params
35
+ @units + @kernel.shape.inject(&:*)
36
+ end
37
+
38
+ def call(inputs)
39
+ build(inputs.shape) unless @built
40
+
41
+ rank = inputs.shape.size
42
+
43
+ if rank > 2
44
+ raise Error, "Rank > 2 not supported yet"
45
+ else
46
+ inputs = TensorFlow.cast(inputs, @dtype)
47
+ outputs = TensorFlow.matmul(inputs, @kernel)
48
+ end
49
+
50
+ if @use_bias
51
+ outputs = NN.bias_add(outputs, @bias)
52
+ end
53
+
54
+ case @activation
55
+ when "relu"
56
+ NN.relu(outputs)
57
+ when "softmax"
58
+ NN.softmax(outputs)
59
+ when nil
60
+ outputs
61
+ else
62
+ raise "Unknown activation: #{@activation}"
63
+ end
6
64
  end
7
65
  end
8
66
  end
@@ -4,6 +4,23 @@ module TensorFlow
4
4
  class Dropout
5
5
  def initialize(rate)
6
6
  end
7
+
8
+ def build(input_shape)
9
+ @output_shape = input_shape
10
+ end
11
+
12
+ def call(inputs)
13
+ # TODO implement
14
+ TensorFlow.identity(inputs)
15
+ end
16
+
17
+ def output_shape
18
+ @output_shape
19
+ end
20
+
21
+ def count_params
22
+ 0
23
+ end
7
24
  end
8
25
  end
9
26
  end
@@ -3,6 +3,21 @@ module TensorFlow
3
3
  module Layers
4
4
  class Flatten
5
5
  def initialize(input_shape: nil)
6
+ @input_shape = input_shape
7
+ end
8
+
9
+ def output_shape
10
+ flattened_dim = @input_shape.inject(&:*)
11
+ [-1, flattened_dim]
12
+ end
13
+
14
+ def count_params
15
+ 0
16
+ end
17
+
18
+ def call(inputs)
19
+ flattened_dim = inputs.shape[1..-1].inject(&:*)
20
+ TensorFlow.reshape(inputs, [-1, flattened_dim])
6
21
  end
7
22
  end
8
23
  end
@@ -0,0 +1,14 @@
1
+ module TensorFlow
2
+ module Keras
3
+ module Losses
4
+ class SparseCategoricalCrossentropy
5
+ def call(target, output)
6
+ output = Math.log(output)
7
+ target = TensorFlow.cast(target, :int64)
8
+ cost, _ = RawOps.sparse_softmax_cross_entropy_with_logits(features: output, labels: target)
9
+ Math.reduce_sum(cost) / TensorFlow.cast(RawOps.size(input: cost), :float)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -2,15 +2,29 @@ module TensorFlow
2
2
  module Keras
3
3
  module Metrics
4
4
  class Mean
5
+ def initialize(name: nil, dtype: :float)
6
+ @dtype = dtype
7
+ @total = Utils.add_weight(name: "total", initializer: "zeros", dtype: @dtype)
8
+ @count = Utils.add_weight(name: "count", initializer: "zeros", dtype: @dtype)
9
+ end
10
+
11
+ def call(*args)
12
+ update_state(*args)
13
+ end
14
+
5
15
  def update_state(values)
6
- input = TensorFlow.convert_to_tensor(values, dtype: :float)
7
- @total = Math.reduce_sum(input)
8
- @count = RawOps.size(input: input)
16
+ input = TensorFlow.convert_to_tensor(values)
17
+ input = TensorFlow.cast(input, @dtype)
18
+ @total.assign_add(Math.reduce_sum(input))
19
+ @count.assign_add(TensorFlow.cast(RawOps.size(input: input), @dtype))
9
20
  end
10
21
 
11
22
  def result
12
23
  RawOps.div_no_nan(x: @total, y: TensorFlow.cast(@count, :float))
13
24
  end
25
+
26
+ def reset_states
27
+ end
14
28
  end
15
29
  end
16
30
  end
@@ -0,0 +1,20 @@
1
+ module TensorFlow
2
+ module Keras
3
+ module Metrics
4
+ class SparseCategoricalAccuracy < Mean
5
+ def update_state(y_true, y_pred)
6
+ y_true = TensorFlow.convert_to_tensor(y_true)
7
+ y_pred = TensorFlow.convert_to_tensor(y_pred)
8
+
9
+ y_pred = RawOps.arg_max(input: y_pred, dimension: -1)
10
+
11
+ if y_pred.dtype != y_true.dtype
12
+ y_pred = TensorFlow.cast(y_pred, y_true.dtype)
13
+ end
14
+
15
+ super(Math.equal(y_true, y_pred))
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,6 @@
1
+ module TensorFlow
2
+ module Keras
3
+ class Model
4
+ end
5
+ end
6
+ end
@@ -25,6 +25,31 @@ module TensorFlow
25
25
  def evaluate(x, y)
26
26
  raise "Not implemented"
27
27
  end
28
+
29
+ def summary
30
+ sep = "_________________________________________________________________\n"
31
+
32
+ output_shape = nil
33
+ @layers.each do |layer|
34
+ layer.build(output_shape) if layer.respond_to?(:build)
35
+ output_shape = layer.output_shape
36
+ end
37
+
38
+ total_params = @layers.map(&:count_params).sum
39
+
40
+ summary = String.new("")
41
+ summary << "Model: \"sequential\"\n"
42
+ summary << sep
43
+ summary << "Layer (type) Output Shape Param # \n"
44
+ summary << "=================================================================\n"
45
+ summary << @layers.map { |l| "%-28s %-25s %-10s\n" % [l.class.name.split("::").last, ([nil] + l.output_shape[1..-1]).inspect, l.count_params] }.join(sep)
46
+ summary << "=================================================================\n"
47
+ summary << "Total params: #{total_params}\n"
48
+ summary << "Trainable params: #{total_params}\n"
49
+ summary << "Non-trainable params: 0\n"
50
+ summary << sep
51
+ puts summary
52
+ end
28
53
  end
29
54
  end
30
55
  end
@@ -0,0 +1,8 @@
1
+ module TensorFlow
2
+ module Keras
3
+ module Optimizers
4
+ class Adam
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ module TensorFlow
2
+ module Keras
3
+ module Preprocessing
4
+ module Image
5
+ class << self
6
+ def load_img(path, target_size: nil)
7
+ img = MiniMagick::Image.open(path)
8
+ if target_size
9
+ # TODO make resize consistent with Python
10
+ img.resize "#{target_size.map(&:to_i).join("x")}!", "-filter", "point"
11
+ end
12
+ img
13
+ end
14
+
15
+ def img_to_array(img)
16
+ Numo::SFloat.cast(img.get_pixels)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -2,6 +2,32 @@ module TensorFlow
2
2
  module Keras
3
3
  module Utils
4
4
  class << self
5
+ def add_weight(name: nil, shape: [], initializer: nil, dtype: :float)
6
+ variable = Variable.new(shape: shape, name: name, dtype: dtype)
7
+ initial_value =
8
+ case initializer
9
+ when "zeros"
10
+ TensorFlow.fill(TensorFlow.convert_to_tensor(shape, dtype: :int64), 0.0)
11
+ when "glorot_uniform"
12
+ # TODO compute fans
13
+ fan_in = shape[0]
14
+ fan_out = shape[1]
15
+ scale = 1.0
16
+ scale /= [1.0, (fan_in + fan_out) / 2.0].max
17
+ limit = ::Math.sqrt(3.0 * scale)
18
+
19
+ minval = -limit
20
+ maxval = limit
21
+
22
+ rnd = RawOps.random_uniform(shape: shape, dtype: :float)
23
+ Math.add(rnd * (maxval - minval), minval)
24
+ else
25
+ raise Error, "Unknown initializer: #{initializer}"
26
+ end
27
+ variable.assign(initial_value)
28
+ variable
29
+ end
30
+
5
31
  def get_file(fname, origin, file_hash: nil, cache_subdir: "datasets")
6
32
  # destination
7
33
  # TODO handle this better
@@ -493,7 +493,7 @@ module TensorFlow
493
493
 
494
494
  def reduction_dims(input_tensor)
495
495
  rank = RawOps.rank(input: input_tensor).value
496
- (0...rank).to_a
496
+ TensorFlow.constant((0...rank).to_a, dtype: :int32)
497
497
  end
498
498
  end
499
499
  end
@@ -29,6 +29,10 @@ module TensorFlow
29
29
  RawOps.range(start: start, limit: limit, delta: delta)
30
30
  end
31
31
 
32
+ def reshape(tensor, shape)
33
+ RawOps.reshape(tensor: tensor, shape: shape)
34
+ end
35
+
32
36
  def squeeze(input, axis: nil)
33
37
  RawOps.squeeze(input: input, squeeze_dims: axis)
34
38
  end
@@ -105,19 +105,9 @@ module TensorFlow
105
105
  when :complex128
106
106
  data_pointer.read_array_of_double(element_count * 2).each_slice(2).map { |v| Complex(*v) }
107
107
  when :string
108
- # string tensor format
109
- # https://github.com/tensorflow/tensorflow/blob/5453aee48858fd375172d7ae22fad1557e8557d6/tensorflow/c/tf_tensor.h#L57
110
- start_offset_size = element_count * 8
111
- offsets = data_pointer.read_array_of_uint64(element_count)
112
- byte_size = FFI.TF_TensorByteSize(tensor_pointer)
108
+ tf_string_size = 24
113
109
  element_count.times.map do |i|
114
- str_len = (offsets[i + 1] || (byte_size - start_offset_size)) - offsets[i]
115
- str = (data_pointer + start_offset_size + offsets[i]).read_bytes(str_len)
116
- dst = ::FFI::MemoryPointer.new(:char, str.bytesize + 100)
117
- dst_len = ::FFI::MemoryPointer.new(:size_t)
118
- FFI.TF_StringDecode(str, str.bytesize, dst, dst_len, @status)
119
- check_status @status
120
- dst.read_pointer.read_bytes(dst_len.read_int32)
110
+ FFI.TF_StringGetDataPointer(data_pointer + i * tf_string_size)
121
111
  end
122
112
  when :bool
123
113
  data_pointer.read_array_of_int8(element_count).map { |v| v == 1 }
@@ -226,20 +216,13 @@ module TensorFlow
226
216
  shape
227
217
  end
228
218
 
229
- # string tensor format
230
- # https://github.com/tensorflow/tensorflow/blob/5453aee48858fd375172d7ae22fad1557e8557d6/tensorflow/c/tf_tensor.h#L57
231
219
  def string_ptr(data)
232
- start_offset_size = data.size * 8
233
- offsets = [0]
234
- data.each do |str|
235
- offsets << offsets.last + str.bytesize + 1
236
- end
237
- data_ptr = ::FFI::MemoryPointer.new(:char, start_offset_size + offsets.pop)
238
- data_ptr.write_array_of_uint64(offsets)
239
- data.zip(offsets) do |str, offset|
240
- dst_len = FFI.TF_StringEncodedSize(str.bytesize)
241
- FFI.TF_StringEncode(str, str.bytesize, data_ptr + start_offset_size + offset, dst_len, @status)
242
- check_status @status
220
+ tf_string_size = 24
221
+ data_ptr = ::FFI::MemoryPointer.new(:char, data.size * tf_string_size)
222
+ data.each_with_index do |str, i|
223
+ offset = data_ptr + i * tf_string_size
224
+ FFI.TF_StringInit(offset)
225
+ FFI.TF_StringCopy(offset, str, str.bytesize)
243
226
  end
244
227
  data_ptr
245
228
  end
@@ -1,9 +1,13 @@
1
1
  module TensorFlow
2
2
  class Variable
3
- def initialize(initial_value, dtype: nil)
3
+ attr_reader :name
4
+
5
+ def initialize(initial_value = nil, dtype: nil, shape: nil, name: nil)
4
6
  @dtype = dtype || Utils.infer_type(Array(initial_value).flatten)
7
+ @shape = shape
8
+ @name = name
5
9
  @pointer = RawOps.var_handle_op(dtype: type_enum, shape: [], shared_name: Utils.default_context.shared_name)
6
- assign(initial_value)
10
+ assign(initial_value) if initial_value
7
11
  end
8
12
 
9
13
  def assign(value)
@@ -42,12 +46,21 @@ module TensorFlow
42
46
  inspect
43
47
  end
44
48
 
49
+ def shape
50
+ read_value.shape
51
+ end
52
+
45
53
  def inspect
46
54
  value = read_value
47
55
  inspection = %w(numo shape dtype).map { |v| "#{v}: #{value.send(v).inspect}"}
56
+ inspection.unshift("name: #{name}") if name
48
57
  "#<#{self.class} #{inspection.join(", ")}>"
49
58
  end
50
59
 
60
+ def to_ptr
61
+ read_value.to_ptr
62
+ end
63
+
51
64
  private
52
65
 
53
66
  def type_enum
@@ -1,3 +1,3 @@
1
1
  module TensorFlow
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tensorflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-24 00:00:00.000000000 Z
11
+ date: 2021-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -52,84 +52,15 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: minitest
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '5'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '5'
97
- - !ruby/object:Gem::Dependency
98
- name: google-protobuf
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: nokogiri
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- description:
126
- email: andrew@chartkick.com
55
+ description:
56
+ email: andrew@ankane.org
127
57
  executables: []
128
58
  extensions: []
129
59
  extra_rdoc_files: []
130
60
  files:
131
61
  - CHANGELOG.md
132
62
  - LICENSE.txt
63
+ - NOTICE.txt
133
64
  - README.md
134
65
  - lib/tensorflow.rb
135
66
  - lib/tensorflow/audio.rb
@@ -149,11 +80,18 @@ files:
149
80
  - lib/tensorflow/keras/datasets/imdb.rb
150
81
  - lib/tensorflow/keras/datasets/mnist.rb
151
82
  - lib/tensorflow/keras/datasets/reuters.rb
83
+ - lib/tensorflow/keras/layers/conv.rb
84
+ - lib/tensorflow/keras/layers/conv2d.rb
152
85
  - lib/tensorflow/keras/layers/dense.rb
153
86
  - lib/tensorflow/keras/layers/dropout.rb
154
87
  - lib/tensorflow/keras/layers/flatten.rb
88
+ - lib/tensorflow/keras/losses/sparse_categorical_crossentropy.rb
155
89
  - lib/tensorflow/keras/metrics/mean.rb
90
+ - lib/tensorflow/keras/metrics/sparse_categorical_accuracy.rb
91
+ - lib/tensorflow/keras/model.rb
156
92
  - lib/tensorflow/keras/models/sequential.rb
93
+ - lib/tensorflow/keras/optimizers/adam.rb
94
+ - lib/tensorflow/keras/preprocessing/image.rb
157
95
  - lib/tensorflow/keras/utils.rb
158
96
  - lib/tensorflow/linalg.rb
159
97
  - lib/tensorflow/math.rb
@@ -167,9 +105,9 @@ files:
167
105
  - lib/tensorflow/version.rb
168
106
  homepage: https://github.com/ankane/tensorflow
169
107
  licenses:
170
- - MIT
108
+ - Apache-2.0
171
109
  metadata: {}
172
- post_install_message:
110
+ post_install_message:
173
111
  rdoc_options: []
174
112
  require_paths:
175
113
  - lib
@@ -177,15 +115,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
177
115
  requirements:
178
116
  - - ">="
179
117
  - !ruby/object:Gem::Version
180
- version: '2.4'
118
+ version: '2.6'
181
119
  required_rubygems_version: !ruby/object:Gem::Requirement
182
120
  requirements:
183
121
  - - ">="
184
122
  - !ruby/object:Gem::Version
185
123
  version: '0'
186
124
  requirements: []
187
- rubygems_version: 3.0.3
188
- signing_key:
125
+ rubygems_version: 3.2.3
126
+ signing_key:
189
127
  specification_version: 4
190
128
  summary: TensorFlow - the end-to-end machine learning platform - for Ruby
191
129
  test_files: []