class VowpalWabbit::Model

Public Class Methods

new(**params) click to toggle source
# File lib/vowpalwabbit/model.rb, line 3
def initialize(**params)
  # add strict parse once exceptions are handled properly
  # https://github.com/VowpalWabbit/vowpal_wabbit/issues/2004
  @params = {quiet: true}.merge(params)
end

Public Instance Methods

coefs() click to toggle source
# File lib/vowpalwabbit/model.rb, line 29
def coefs
  num_weights = FFI.VW_Num_Weights(handle)
  coefs = {}
  num_weights.times.map do |i|
    weight = FFI.VW_Get_Weight(handle, i, 0)
    coefs[i] = weight if weight != 0
  end
  coefs
end
fit(x, y = nil) click to toggle source
# File lib/vowpalwabbit/model.rb, line 9
def fit(x, y = nil)
  @handle = nil
  partial_fit(x, y)
end
load_model(filename) click to toggle source
# File lib/vowpalwabbit/model.rb, line 50
def load_model(filename)
  bin_str = File.binread(filename)
  model_data = ::FFI::MemoryPointer.new(:char, bin_str.bytesize)
  model_data.put_bytes(0, bin_str)
  @handle = FFI.VW_InitializeWithModel(param_str(@params), model_data, bin_str.bytesize)
  nil
end
partial_fit(x, y = nil) click to toggle source
# File lib/vowpalwabbit/model.rb, line 14
def partial_fit(x, y = nil)
  each_example(x, y) do |example|
    FFI.VW_Learn(handle, example)
  end
  nil
end
predict(x) click to toggle source
# File lib/vowpalwabbit/model.rb, line 21
def predict(x)
  out = []
  each_example(x) do |example|
    out << predict_example(example)
  end
  out
end
save_model(filename) click to toggle source
# File lib/vowpalwabbit/model.rb, line 39
def save_model(filename)
  buffer_handle = ::FFI::MemoryPointer.new(:pointer)
  output_data = ::FFI::MemoryPointer.new(:pointer)
  output_size = ::FFI::MemoryPointer.new(:size_t)
  FFI.VW_CopyModelData(handle, buffer_handle, output_data, output_size)
  bin_str = output_data.read_pointer.read_string(output_size.read(:size_t))
  FFI.VW_FreeIOBuf(buffer_handle.read_pointer)
  File.binwrite(filename, bin_str)
  nil
end

Private Instance Methods

check_param(v) click to toggle source
# File lib/vowpalwabbit/model.rb, line 84
def check_param(v)
  raise ArgumentError, "Invalid parameter" if /[[:space:]]/.match(v)
end
each_example(x, y = nil) { |example| ... } click to toggle source
# File lib/vowpalwabbit/model.rb, line 111
def each_example(x, y = nil)
  # path to a file
  if x.is_a?(String)
    raise ArgumentError, "Cannot pass y with file" if y

    file_handle = FFI.VW_InitializeA(param_str(data: x, quiet: true))
    FFI.VW_StartParser(file_handle)
    loop do
      example = FFI.VW_GetExample(file_handle)
      break if example.read_pointer.null?
      yield example
      FFI.VW_FinishExample(file_handle, example)
    end
    FFI.VW_EndParser(file_handle)
    FFI.VW_Finish(file_handle)
  else
    x = x.to_a
    if y
      y = y.to_a
      raise ArgumentError, "x and y must have same size" if x.size != y.size
    end

    x.zip(y || []) do |xi, yi|
      line =
        if xi.is_a?(String)
          xi
        else
          "#{yi} 1 | #{xi.map.with_index { |v, i| "#{i}:#{v}" }.join(" ")}"
        end

      example = FFI.VW_ReadExampleA(handle, line)
      yield example
      FFI.VW_FinishExample(handle, example)
    end
  end
end
handle() click to toggle source

TODO clean-up handle

# File lib/vowpalwabbit/model.rb, line 61
def handle
  @handle ||= FFI.VW_InitializeA(param_str(@params))
end
param_str(params) click to toggle source
# File lib/vowpalwabbit/model.rb, line 65
def param_str(params)
  args =
    params.map do |k, v|
      check_param(k.to_s)
      check_param(v.to_s)

      if v == true
        "--#{k}"
      elsif !v
        nil
      elsif k.size == 1
        "-#{k} #{v}"
      else
        "--#{k} #{v}"
      end
    end
  args.compact.join(" ")
end
predict_example(example) click to toggle source
# File lib/vowpalwabbit/model.rb, line 88
def predict_example(example)
  if @params[:cb]
    FFI.VW_PredictCostSensitive(handle, example)
  else
    FFI.VW_Predict(handle, example)
  end
end
predict_for_score(x, y) click to toggle source

get both in one pass for efficiency

# File lib/vowpalwabbit/model.rb, line 97
def predict_for_score(x, y)
  if x.is_a?(String) && !y
    y_pred = []
    y = []
    each_example(x) do |example|
      y_pred << predict_example(example)
      y << FFI.VW_GetLabel(example)
    end
    [y_pred, y]
  else
    [predict(x), y]
  end
end