Class: RubyZero::Core::Tensor

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyzero/core/cast.rb,
lib/rubyzero/core/tensor.rb,
lib/rubyzero/core/tensor_backward.rb,
lib/rubyzero/core/tensor_operators.rb,
lib/rubyzero/core/tensor_initialize_methods.rb,
lib/rubyzero/core/functions/tensor_functions.rb

Overview

Tensor class

Constant Summary collapse

CAST_PRIORITY =
[
    RubyZero::Core::DataTypes::Boolean,
    RubyZero::Core::DataTypes::UInt8,
    RubyZero::Core::DataTypes::Int8,
    RubyZero::Core::DataTypes::UInt16,
    RubyZero::Core::DataTypes::Int16,
    RubyZero::Core::DataTypes::UInt32,
    RubyZero::Core::DataTypes::Int32,
    RubyZero::Core::DataTypes::UInt64,
    RubyZero::Core::DataTypes::Int64,
    RubyZero::Core::DataTypes::Float32,
    RubyZero::Core::DataTypes::Float64,
    RubyZero::Core::DataTypes::Complex64,
    RubyZero::Core::DataTypes::Complex128,
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data, dtype: nil, device: nil) ⇒ Tensor

Returns a new instance of Tensor.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rubyzero/core/tensor.rb', line 5

def initialize(data, dtype: nil, device: nil)
    @device = device || RubyZero.device(:cpu)
    @grad_fn = nil
    @grad = nil
    @requires_grad = false

    # check data type

    if data.is_a?(Array)
        if dtype
            @data = dtype.get_type_on_calculator(device)[*data]
        else
            @data = @device.caluculator::NArray[*data]
        end
    elsif data.is_a?(Numeric)
        if dtype
            @data = dtype.get_type_on_calculator(device)[data]
        else
            @data = @device.caluculator::NArray[data]
        end
    elsif data.is_a?(Numo::NArray)
        @data = data
    else 
        raise Execptions::TypeNotSupported, "Tensor data type not supported: #{data.class}"
    end
    @dtype = DataTypes.from_xmo_dtype(@data.class)
end

Instance Attribute Details

#dataObject

Returns the value of attribute data.



4
5
6
# File 'lib/rubyzero/core/tensor.rb', line 4

def data
  @data
end

#deviceObject

Returns the value of attribute device.



4
5
6
# File 'lib/rubyzero/core/tensor.rb', line 4

def device
  @device
end

#gradObject

Returns the value of attribute grad.



4
5
6
# File 'lib/rubyzero/core/tensor.rb', line 4

def grad
  @grad
end

#grad_fnObject

Returns the value of attribute grad_fn.



4
5
6
# File 'lib/rubyzero/core/tensor.rb', line 4

def grad_fn
  @grad_fn
end

#requires_gradObject

Returns the value of attribute requires_grad.



4
5
6
# File 'lib/rubyzero/core/tensor.rb', line 4

def requires_grad
  @requires_grad
end

Class Method Details

.ones(shape, dtype: RubyZero::Core::DataTypes::Float64, device: RubyZero.device(:cpu)) ⇒ Object

initialize new tensor with given shape which filled with ones.



17
18
19
20
21
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 17

def self.ones(shape, dtype: RubyZero::Core::DataTypes::Float64, device: RubyZero.device(:cpu))
    dtype = dtype.get_type_on_calculator(device)
    data = dtype.ones(shape)
    Tensor.new(data, dtype:dtype, device:device)
end

.rand(shape, dtype: RubyZero::Core::DataTypes::Float64, device: RubyZero.device(:cpu)) ⇒ Object

initialize new tensor with given shape which filled with random values.



41
42
43
44
45
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 41

def self.rand(shape, dtype: RubyZero::Core::DataTypes::Float64, device: RubyZero.device(:cpu))
    dtype = dtype.get_type_on_calculator(device)
    data = dtype.new(shape).rand
    Tensor.new(data, dtype:dtype, device:device)
end

.randn(shape, dtype: RubyZero::Core::DataTypes::Float64, device: RubyZero.device(:cpu)) ⇒ Object

initialize new tensor with given shape which filled with random values.



29
30
31
32
33
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 29

def self.randn(shape, dtype: RubyZero::Core::DataTypes::Float64, device: RubyZero.device(:cpu))
    dtype = dtype.get_type_on_calculator(device)
    data = dtype.new(shape).rand_norm
    Tensor.new(data, dtype:dtype, device:device)
end

.stack(tensors, axis: 0) ⇒ Object



52
53
54
55
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 52

def self.stack(tensors, axis:0)
    t = Tensor.new(tensors.map{|t| t.data})
    return t
end

.zeros(shape, dtype: RubyZero::Core::DataTypes::Float64, device: RubyZero.device(:cpu)) ⇒ Object

initialize new tensor with given shape which filled with zeros.



4
5
6
7
8
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 4

def self.zeros(shape, dtype: RubyZero::Core::DataTypes::Float64, device: RubyZero.device(:cpu))
    dtype = dtype.get_type_on_calculator(device)
    data = dtype.zeros(shape)
    Tensor.new(data, dtype:dtype, device:device)
end

Instance Method Details

#*(other) ⇒ Object



9
10
11
12
13
14
15
# File 'lib/rubyzero/core/tensor_operators.rb', line 9

def *(other)
    if other.is_a?(Numeric)
        RubyZero::Core::Functions::MulScalar.new(other).call(self)
    else
        RubyZero::Core::Functions::Mul.new().call(self, other)
    end
end

#+(other) ⇒ Object



3
4
5
# File 'lib/rubyzero/core/tensor_operators.rb', line 3

def +(other)
    RubyZero::Core::Functions::Add.new().call(self, other)
end

#-(other) ⇒ Object



6
7
8
# File 'lib/rubyzero/core/tensor_operators.rb', line 6

def -(other)
    RubyZero::Core::Functions::Sub.new().call(self, other)
end

#-@Object



23
24
25
# File 'lib/rubyzero/core/tensor_operators.rb', line 23

def -@
    RubyZero::Core::Functions::Neg.new().call(self)
end

#/(other) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/rubyzero/core/tensor_operators.rb', line 16

def /(other)
    if other.is_a?(Numeric)
        RubyZero::Core::Functions::DivScalar.new(other).call(self)
    else
        RubyZero::Core::Functions::Div.new().call(self, other)
    end
end

#backwardObject



3
4
5
6
7
8
9
10
11
12
13
14
15
# File 'lib/rubyzero/core/tensor_backward.rb', line 3

def backward()
    return unless @grad_fn
    @grad ||= ones_like
    dx = @grad_fn.backward(@grad)
    self.grad_fn.inputs.each_with_index do |input, i|
        if input.grad
            input.grad += dx[i]
        else
            input.grad = dx[i]
        end
        input.backward()
    end
end

#cast_to(dtype) ⇒ Object



19
20
21
22
23
# File 'lib/rubyzero/core/cast.rb', line 19

def cast_to(dtype)
    @dtype = dtype
    @data = dtype.get_type_on_calculator(@device).cast(@data)
    return self
end

#detachObject

detach from graph



52
53
54
# File 'lib/rubyzero/core/tensor.rb', line 52

def detach
    @grad_fn = nil
end

#dot(other) ⇒ Object



115
116
117
118
119
120
121
# File 'lib/rubyzero/core/functions/tensor_functions.rb', line 115

def dot(other)
    if other.is_a?(RubyZero::Core::Tensor)
        return RubyZero::Core::Functions::DotProduct.new().call(self, other)
    else
        return self*other
    end
end

#dtypeDataTypes::DataType

get data type

Returns:



33
34
35
# File 'lib/rubyzero/core/tensor.rb', line 33

def dtype
    @dtype
end

#inspectString

get tensor summary

Returns:

  • (String)


43
44
45
46
# File 'lib/rubyzero/core/tensor.rb', line 43

def inspect
    numo_inspect = @data.inspect.split("\n")[1..nil].join("\n")
    return "#{dtype}#shape=#{shape.to_a}\n#{numo_inspect}\ngrad_fn=#{@grad_fn.class}"
end

#mean(axis: 0) ⇒ Object



112
113
114
# File 'lib/rubyzero/core/functions/tensor_functions.rb', line 112

def mean(axis: 0)
    return RubyZero::Core::Functions::Mean.new(axis).call(self)
end

#ones_likeObject

initialize new tensor with given another tensor’s shape which filled with ones.



24
25
26
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 24

def ones_like()
    Tensor.ones(self.shape, dtype:self.dtype, device:self.device)
end

#rand_likeObject

initialize new tensor with given another tensor’s shape which filled with random values.



48
49
50
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 48

def rand_like()
    Tensor.rand(self.shape, dtype: self.dtype, device:self.device)
end

#randn_likeObject

initialize new tensor with given another tensor’s shape which filled with random values.



36
37
38
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 36

def randn_like()
    Tensor.randn(self.shape, dtype:self.dtype, device:self.device)
end

#repeat(repeats, axis: 0) ⇒ Object



106
107
108
# File 'lib/rubyzero/core/functions/tensor_functions.rb', line 106

def repeat(repeats, axis:0)
    return RubyZero::Core::Functions::Repeat.new(axis, repeats).call(self)
end

#requires_grad?Boolean

Returns:



48
49
50
# File 'lib/rubyzero/core/tensor.rb', line 48

def requires_grad?
    @requires_grad
end

#reshape(shape) ⇒ Object



100
101
102
# File 'lib/rubyzero/core/functions/tensor_functions.rb', line 100

def reshape(shape)
    return RubyZero::Core::Functions::Reshape.new(shape).call(self)
end

#shapeArray<Integer>

get shape

Returns:

  • (Array<Integer>)


38
39
40
# File 'lib/rubyzero/core/tensor.rb', line 38

def shape
    @data.shape
end

#sum(axis: 0) ⇒ Object



109
110
111
# File 'lib/rubyzero/core/functions/tensor_functions.rb', line 109

def sum(axis: 0)
    return RubyZero::Core::Functions::Sum.new(axis).call(self)
end

#swapaxes(axis1, axis2) ⇒ Object



103
104
105
# File 'lib/rubyzero/core/functions/tensor_functions.rb', line 103

def swapaxes(axis1, axis2)
    return RubyZero::Core::Functions::SwapAxes.new(axis1, axis2).call(self)
end

#zeros_likeObject

initialize new tensor with given another tensor’s shape which filled with zeros.



12
13
14
# File 'lib/rubyzero/core/tensor_initialize_methods.rb', line 12

def zeros_like()
    Tensor.zeros(self.shape, dtype:self.dtype, device:self.device)
end