Class: TensorStream::OpMaker

Inherits:
Object
  • Object
show all
Defined in:
lib/tensor_stream/op_maker.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(op) ⇒ OpMaker

Returns a new instance of OpMaker.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/tensor_stream/op_maker.rb', line 7

def initialize(op)
  @operation = op
  @parameters = []
  @options = {}
  @gradient = nil
  @supports_broadcast = false
  @data_type_coercion = false
  @exclude = false
  @description = []
  @aliases = []
  @custom = []
  @infer_type_proc = lambda { |tensor|
    next nil if tensor.inputs[0].nil?
    next tensor.inputs[0].shape.shape if tensor.inputs.size == 1

    TensorStream::TensorShape.infer_shape(tensor.inputs[0].shape.shape, tensor.inputs[1].shape.shape) if tensor.inputs.size == 2 && tensor.inputs[0] && tensor.inputs[1]
  }
end

Instance Attribute Details

#aliasesObject (readonly)

Returns the value of attribute aliases.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def aliases
  @aliases
end

#check_typesObject (readonly)

Returns the value of attribute check_types.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def check_types
  @check_types
end

#customObject (readonly)

Returns the value of attribute custom.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def custom
  @custom
end

#data_type_coercionObject (readonly)

Returns the value of attribute data_type_coercion.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def data_type_coercion
  @data_type_coercion
end

#descriptionObject (readonly)

Returns the value of attribute description.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def description
  @description
end

#excludeObject (readonly)

Returns the value of attribute exclude.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def exclude
  @exclude
end

#gradientObject (readonly)

Returns the value of attribute gradient.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def gradient
  @gradient
end

#infer_type_procObject (readonly)

Returns the value of attribute infer_type_proc.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def infer_type_proc
  @infer_type_proc
end

#operationObject (readonly)

Returns the value of attribute operation.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def operation
  @operation
end

#optionsObject (readonly)

Returns the value of attribute options.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def options
  @options
end

#parametersObject (readonly)

Returns the value of attribute parameters.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def parameters
  @parameters
end

#supports_broadcastObject (readonly)

Returns the value of attribute supports_broadcast.



2
3
4
# File 'lib/tensor_stream/op_maker.rb', line 2

def supports_broadcast
  @supports_broadcast
end

Class Method Details

.define_operation(op_code, &block) ⇒ Object



41
42
43
44
45
46
# File 'lib/tensor_stream/op_maker.rb', line 41

def self.define_operation(op_code, &block)
  @ops ||= {}
  op_maker = TensorStream::OpMaker.new(op_code.to_sym)
  block.call(op_maker)
  @ops[op_code.to_sym] = op_maker
end

.each_op(&block) ⇒ Object



61
62
63
64
65
# File 'lib/tensor_stream/op_maker.rb', line 61

def self.each_op(&block)
  @ops.values.sort_by { |op| op.operation }.reject(&:exclude).each do |op|
    block.call(op)
  end
end

.gradient_op(context_caller, node, grad) ⇒ Object

call an operations’ gradient definition



49
50
51
52
53
# File 'lib/tensor_stream/op_maker.rb', line 49

def self.gradient_op(context_caller, node, grad)
  raise "No derivative op defined for #{node.operation}" if @ops[node.operation].nil? || @ops[node.operation].gradient.nil?

  context_caller.instance_exec(grad, node, node.inputs, &@ops[node.operation].gradient)
end

.infer_shape(context_caller, tensor) ⇒ Object



55
56
57
58
59
# File 'lib/tensor_stream/op_maker.rb', line 55

def self.infer_shape(context_caller, tensor)
  return nil unless @ops[tensor.operation]

  context_caller.instance_exec(tensor, &@ops[tensor.operation].infer_type_proc)
end

.scanObject



34
35
36
37
38
39
# File 'lib/tensor_stream/op_maker.rb', line 34

def self.scan
  op_files = Dir[File.join(File.dirname(__FILE__), "ops", "*.rb")]
  op_files.each { |file|
    load File.join("tensor_stream", "ops", File.basename(file))
  }
end

Instance Method Details

#add_custom(custom_code) ⇒ Object



30
31
32
# File 'lib/tensor_stream/op_maker.rb', line 30

def add_custom(custom_code)
  @custom << custom_code
end

#apply_data_type_coercion!Object



135
136
137
# File 'lib/tensor_stream/op_maker.rb', line 135

def apply_data_type_coercion!
  @data_type_coercion = true
end

#check_types?Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/tensor_stream/op_maker.rb', line 155

def check_types?
  @check_types
end

#data_type_coercion?Boolean

Returns:

  • (Boolean)


151
152
153
# File 'lib/tensor_stream/op_maker.rb', line 151

def data_type_coercion?
  @data_type_coercion
end

#default_with_nil(v) ⇒ Object



175
176
177
# File 'lib/tensor_stream/op_maker.rb', line 175

def default_with_nil(v)
  v == :nil ? 'nil' : v
end

#define_gradient(&block) ⇒ Object



117
118
119
# File 'lib/tensor_stream/op_maker.rb', line 117

def define_gradient(&block)
  @gradient = block
end

#define_shape(&block) ⇒ Object



121
122
123
# File 'lib/tensor_stream/op_maker.rb', line 121

def define_shape(&block)
  @infer_type_proc = block
end

#description_linesObject



79
80
81
# File 'lib/tensor_stream/op_maker.rb', line 79

def description_lines
  description.map { |line| line.split("\n") }.flatten
end

#exclude!Object



75
76
77
# File 'lib/tensor_stream/op_maker.rb', line 75

def exclude!
  @exclude = true
end

#expand_options(print_defaults) ⇒ Object



159
160
161
162
163
# File 'lib/tensor_stream/op_maker.rb', line 159

def expand_options(print_defaults)
  @options.map { |k, v|
    print_defaults && v[:default_value] ? "#{k}: #{default_with_nil(v[:default_value])}" : "#{k}:"
  }
end

#expand_params(print_defaults) ⇒ Object



125
126
127
128
129
# File 'lib/tensor_stream/op_maker.rb', line 125

def expand_params(print_defaults)
  @parameters.map { |param|
    print_defaults && param[:default_value] ? "#{param[:name]} = #{default_with_nil(param[:default_value])}" : "#{param[:name]}"
  }
end

#generate_bodyObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/tensor_stream/op_maker.rb', line 83

def generate_body
  body = []
  parameters.select { |p| p[:validate] }.each do |p|
    body << "check_allowed_types(#{p[:name]}, TensorStream::Ops::#{p[:validate]})"
  end
  if data_type_coercion?
    body << "#{expand_params(false).join(', ')} = apply_data_type_coercion(#{expand_params(false).join(', ')})"
  end
  if check_types?
    body << "check_data_types(#{expand_params(false).join(', ')})"
  end
  custom.each do |c|
    body << c
  end
  body << "_op(:#{operation}, #{(expand_params(false) + options_call).join(', ')})"
  body.map { |line| "      #{line}"}.join("\n")
end

#option(name, description, default_value = nil, options = {}) ⇒ Object



113
114
115
# File 'lib/tensor_stream/op_maker.rb', line 113

def option(name, description, default_value = nil, options = {})
  @options[name] = { description: description, default_value: default_value, options: options }
end

#options_callObject



165
166
167
168
169
170
171
172
173
# File 'lib/tensor_stream/op_maker.rb', line 165

def options_call
  @options.map { |k, v|
    if v.dig(:options, :alias)
      "#{v.dig(:options, :alias)}: #{k}"
    else
      "#{k}: #{k}"
    end
  }
end

#other_names(aliases) ⇒ Object



26
27
28
# File 'lib/tensor_stream/op_maker.rb', line 26

def other_names(aliases)
  @aliases += aliases
end

#parameter(name, description, default_value = nil, validate: nil) ⇒ Object

adds a parameter to the op



104
105
106
107
108
109
110
111
# File 'lib/tensor_stream/op_maker.rb', line 104

def parameter(name, description, default_value = nil, validate: nil)
  @parameters << {
    name: name.to_s,
    description: description,
    default_value: default_value,
    validate: validate
  }
end

#parameters_must_have_same_data_type!Object



131
132
133
# File 'lib/tensor_stream/op_maker.rb', line 131

def parameters_must_have_same_data_type!
  @check_types = true
end

#supports_broadcasting!Object



139
140
141
142
143
144
145
# File 'lib/tensor_stream/op_maker.rb', line 139

def supports_broadcasting!
  if (@parameters.size> 1)
    @supports_broadcast = true
  else
    raise "Ops with parameters < 2 cannot support broadcasting"
  end
end

#supports_broadcasting?Boolean

Returns:

  • (Boolean)


147
148
149
# File 'lib/tensor_stream/op_maker.rb', line 147

def supports_broadcasting?
  @supports_broadcast
end

#what_it_does(description) ⇒ Object



67
68
69
# File 'lib/tensor_stream/op_maker.rb', line 67

def what_it_does(description)
  @description << description
end

#what_it_does_code(description) ⇒ Object



71
72
73
# File 'lib/tensor_stream/op_maker.rb', line 71

def what_it_does_code(description)
  @description << "<tt>#{description}</tt>"
end