Отличный способ перенаправить стандартный вывод в стринг,
почерпнут
на SO:
Code:
def with_captured_stdout
original_stdout = $stdout
$stdout = StringIO.new
yield
$stdout.string
ensure
$stdout = original_stdout
end
А далее - эксклюзив от
Hubbitus-a
в контексте статьи блога
Neural Network in Ruby. Experiments and reflections
; на основе скрипта, иллюстрирующего работу гема
ruby-fann - прототип, как перехватить вывод и записать в файл:
Code:
require 'csv'
require 'ruby-fann'
require 'tempfile'
# https://stackoverflow.com/questions/4459330/how-do-i-temporarily-redirect-stderr-in-ruby/4459463#4459463
# require "stringio"
# def capture_stderr
# # The output stream must be an IO-like object. In this case we capture it in
# # an in-memory IO object so we can return the string value. You can assign any
# # IO object here.
# previous_stderr, $stderr = $stderr, StringIO.new
# yield
# $stderr.string
# ensure
# # Restore the previous value of stderr (typically equal to STDERR).
# $stderr = previous_stderr
# end
def capture_stdout(&block)
stdout_orig = $stdout
stdout_mock = StringIO.new
$stdout = stdout_mock
begin
result = block.call
ensure
$stdout = stdout_orig
end
[result, stdout_mock.string]
end
# Recompilation of https://stackoverflow.com/questions/4459330/how-do-i-temporarily-redirect-stderr-in-ruby/4459463#4459463 (which can't be used because of natve extension writes)
# and https://stackoverflow.com/questions/9026977/how-to-silence-printf-called-from-within-a-ruby-c-extension/9073643#9073643
# @TODO use temporary file (https://ruby-doc.org/stdlib-2.4.0/libdoc/tempfile/rdoc/Tempfile.html) and re-read it at end
def silence_stdout(log = '/dev/null')
orig = $stdout.dup
$stdout.reopen(File.new(log, 'w'))
begin
yield
ensure
$stdout = orig
end
end
x_data = []
y_data = []
# Load data from CSV file into two arrays - one for independent variables X and one for the dependent variable Y
CSV.foreach("./data/admission.csv", :headers => false) do |row|
x_data.push( [row[0].to_f, row[1].to_f] )
#x_data.push( [row[0].to_f, row[1].to_f] )
y_data.push( [row[2].to_i] )
end
# Divide data into a training set and test set
test_size_percentange = 20.0 # 20.0%
test_set_size = x_data.size * (test_size_percentange/100.to_f)
test_x_data = x_data[0 .. (test_set_size-1)]
test_y_data = y_data[0 .. (test_set_size-1)]
training_x_data = x_data[test_set_size .. x_data.size]
training_y_data = y_data[test_set_size .. y_data.size]
# Setup training data model
train = RubyFann::TrainData.new( :inputs=> training_x_data, :desired_outputs=>training_y_data )
# Setup model and train using training data
model = RubyFann::Standard.new(
num_inputs: 2,
hidden_neurons: [6],
num_outputs: 1 )
silence_stdout('ttt.log') do
# 5000 max_epochs, 100 errors between reports and 0.01 desired mean-squared-error
model.train_on_data(train, 5000, 500, 0.01)
end
# Predict single class
prediction = model.run( [45, 85] )
# Round the output to get the prediction
puts "Algorithm predicted class: #{prediction.map{ |e| e.round }}"
predicted = []
test_x_data.each do |params|
predicted.push( model.run(params).map{ |e| e.round } )
end
correct = predicted.collect.with_index { |e,i| (e == test_y_data[i]) ? 1 : 0 }.inject{ |sum,e| sum+e }
puts "Accuracy: #{((correct.to_f / test_set_size) * 100).round(2)}% - test set of size #{test_size_percentange}%"