grx-tensor 0.1.0 → 0.2.1

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.
data/lib/grx/utils.rb ADDED
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GRX
4
+ module Utils
5
+ # ================================================================
6
+ # clip_grad_norm! — Clips gradients of parameter collection so their
7
+ # combined L2 norm does not exceed max_norm.
8
+ # Prevents exploding gradient problems during deep network training.
9
+ # ================================================================
10
+ def self.clip_grad_norm!(parameters, max_norm)
11
+ max_norm = max_norm.to_f
12
+ total_norm_sq = 0.0
13
+ parameters.each do |p|
14
+ next unless p.grad
15
+ total_norm_sq += p.grad.square.to_a.sum
16
+ end
17
+ total_norm = Math.sqrt(total_norm_sq)
18
+ clip_coef = max_norm / (total_norm + 1e-6)
19
+ if clip_coef < 1.0
20
+ parameters.each do |p|
21
+ next unless p.grad
22
+ p.grad = p.grad.scale(clip_coef)
23
+ end
24
+ end
25
+ total_norm
26
+ end
27
+
28
+ # ================================================================
29
+ # one_hot — Generates a 2D One-Hot encoded Tensor from class indices
30
+ # ================================================================
31
+ def self.one_hot(indices, num_classes: nil, requires_grad: false)
32
+ ids = indices.is_a?(Tensor) ? indices.to_a.map(&:to_i) : Array(indices).map(&:to_i)
33
+ c = num_classes || (ids.empty? ? 0 : ids.max + 1)
34
+ n = ids.size
35
+ matrix_data = Array.new(n * c, 0.0)
36
+ ids.each_with_index do |class_id, row|
37
+ raise IndexError, "Class index #{class_id} out of bounds [0, #{c})" if class_id < 0 || class_id >= c
38
+ matrix_data[row * c + class_id] = 1.0
39
+ end
40
+ Tensor.create(matrix_data, [n, c], requires_grad: requires_grad)
41
+ end
42
+ end
43
+ end
data/lib/grx/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GRX
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.1"
5
5
  end
data/lib/grx.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # =====================================================================
4
- # GRX — Framework de tensores con autograd y núcleo C+SIMD
4
+ # GRX — Tensor framework with autograd and C+SIMD compute core
5
5
  # require "grx"
6
6
  # =====================================================================
7
7
 
@@ -10,12 +10,15 @@ require_relative "grx/errors"
10
10
  require_relative "grx/c_api"
11
11
  require_relative "grx/storage"
12
12
  require_relative "grx/tensor"
13
+ require_relative "grx/serialization"
13
14
  require_relative "grx/nn"
14
15
  require_relative "grx/optim"
15
16
  require_relative "grx/loss"
17
+ require_relative "grx/data"
18
+ require_relative "grx/utils"
16
19
 
17
20
  module GRX
18
- # Acceso rápido
21
+ # Quick factory helpers
19
22
  def self.tensor(data, shape, requires_grad: false)
20
23
  Tensor.create(data, shape, requires_grad: requires_grad)
21
24
  end
@@ -34,16 +37,29 @@ module GRX
34
37
  end
35
38
 
36
39
  def self.randn(shape, requires_grad: false)
37
- # Box-Muller desde Ruby (el C lo hace más rápido vía he_normal)
40
+ # Box-Muller from Ruby (C backend executes faster via he_normal)
38
41
  n = shape.reduce(1, :*)
39
42
  data = []
40
43
  (n / 2.0).ceil.times do
41
- u1 = ::Kernel.rand; u1 = ::Kernel.rand while u1 < 1e-15
44
+ u1 = ::Kernel.rand
45
+ u1 = ::Kernel.rand while u1 < 1e-15
42
46
  u2 = ::Kernel.rand
43
47
  r = Math.sqrt(-2.0 * Math.log(u1))
44
- data << r * Math.cos(2 * Math::PI * u2)
45
- data << r * Math.sin(2 * Math::PI * u2)
48
+ data << (r * Math.cos(2 * Math::PI * u2))
49
+ data << (r * Math.sin(2 * Math::PI * u2))
46
50
  end
47
51
  Tensor.create(data.first(n), shape, requires_grad: requires_grad)
48
52
  end
53
+
54
+ def self.c_loaded?
55
+ CAPI::LOADED
56
+ end
57
+
58
+ def self.mode
59
+ CAPI::LOADED ? :c : :ruby
60
+ end
61
+
62
+ def self.simd_mode
63
+ CAPI.simd_mode
64
+ end
49
65
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grx-tensor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
- - Angel Gabriel Garcia Razo
7
+ - Razo
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
@@ -67,8 +67,9 @@ dependencies:
67
67
  version: '2.0'
68
68
  description: |
69
69
  GRX brings PyTorch-style tensor operations to Ruby. Every arithmetic op,
70
- activation, and optimizer step runs through a native C library compiled
71
- with AVX2+FMA SIMD. Ruby is the interface C does the work.
70
+ activation, and optimizer step runs through a native C library with
71
+ dynamic multi-target SIMD dispatch (AVX2+FMA, SSE, and scalar fallback).
72
+ Ruby is the interface — C does the work.
72
73
 
73
74
  Features: autograd, SGD/Adam optimizers, Linear/Sequential/Dropout/BatchNorm
74
75
  layers, MSE/BCE/CrossEntropy loss functions, Xavier and He weight init.
@@ -81,7 +82,9 @@ extensions:
81
82
  extra_rdoc_files: []
82
83
  files:
83
84
  - CHANGELOG.md
85
+ - GUIA_PRINCIPIANTES.md
84
86
  - LICENSE.txt
87
+ - README.es.md
85
88
  - README.md
86
89
  - ext/grx/extconf.rb
87
90
  - ext/grx/grx_core.c
@@ -91,12 +94,15 @@ files:
91
94
  - grx-tensor.gemspec
92
95
  - lib/grx.rb
93
96
  - lib/grx/c_api.rb
97
+ - lib/grx/data.rb
94
98
  - lib/grx/errors.rb
95
99
  - lib/grx/loss.rb
96
100
  - lib/grx/nn.rb
97
101
  - lib/grx/optim.rb
102
+ - lib/grx/serialization.rb
98
103
  - lib/grx/storage.rb
99
104
  - lib/grx/tensor.rb
105
+ - lib/grx/utils.rb
100
106
  - lib/grx/version.rb
101
107
  homepage: https://github.com/Gabo-Razo/grx-tensor
102
108
  licenses:
@@ -107,36 +113,39 @@ metadata:
107
113
  bug_tracker_uri: https://github.com/Gabo-Razo/grx-tensor/issues
108
114
  post_install_message: |2+
109
115
 
110
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
111
- GRX-Tensor 0.1.0 installed
112
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
116
+ ============================================================
117
+ GRX-Tensor 0.2.1
118
+ ============================================================
113
119
 
114
- Compile the C extension to enable AVX2+FMA SIMD:
120
+ [ENGLISH]
121
+ Thank you for choosing and using GRX-Tensor!
115
122
 
116
- Linux / macOS: make -C ext/unix
117
- Windows: make -C ext/windows -f Makefile.mingw
123
+ * Native C acceleration with dynamic SIMD dispatch
124
+ (AVX2+FMA, SSE, and portable scalar C) is built and
125
+ configured automatically.
126
+ * Windows Note: Native C acceleration is supported when
127
+ using RubyInstaller with DevKit (MSYS2 / MinGW-w64).
128
+ Standalone pre-compiled Windows binaries are currently
129
+ in active development.
130
+ * Documentation, guides, and tutorials:
131
+ https://github.com/Gabo-Razo/grx-tensor
118
132
 
119
- Without it, GRX runs in pure Ruby fallback mode (slower but correct).
133
+ ----------------------------------------------------------
120
134
 
121
- Quick start:
135
+ [ESPAÑOL]
136
+ Muchas gracias por elegir y utilizar GRX-Tensor!
122
137
 
123
- require "grx"
138
+ * La aceleracion nativa en C con despacho dinamico SIMD
139
+ (AVX2+FMA, SSE y C escalar portable) se compila y
140
+ configura de forma totalmente automatica.
141
+ * Nota para Windows: La aceleracion nativa esta soportada
142
+ al utilizar RubyInstaller con DevKit (MSYS2 / MinGW-w64).
143
+ Los binarios pre-compilados independientes para Windows
144
+ se encuentran actualmente en desarrollo activo.
145
+ * Documentacion, guias y tutoriales:
146
+ https://github.com/Gabo-Razo/grx-tensor
124
147
 
125
- a = GRX.tensor([1.0, 2.0, 3.0], [3], requires_grad: true)
126
- b = GRX.tensor([4.0, 5.0, 6.0], [3], requires_grad: true)
127
- c = a + b
128
- c.backward
129
- puts a.grad.to_a # [1.0, 1.0, 1.0]
130
-
131
- net = GRX::NN::Sequential.new(
132
- GRX::NN::Linear.new(4, 16),
133
- GRX::NN::ReLU.new,
134
- GRX::NN::Linear.new(16, 1)
135
- )
136
- opt = GRX::Optim::Adam.new(net.parameters, lr: 0.001)
137
-
138
- Docs: https://github.com/Gabo-Razo/grx-tensor
139
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
148
+ ============================================================
140
149
 
141
150
  rdoc_options: []
142
151
  require_paths: