@@ -390,28 +390,14 @@ def self.load_checkpoint(storage:, checkpoint_id:)
390390 # end
391391 # classifier.fit
392392 #
393- # @rbs (String | Symbol, IO, ?batch_size: Integer) { (Streaming::Progress) -> void } -> void
394- def train_from_stream ( category , io , batch_size : Streaming ::DEFAULT_BATCH_SIZE )
395- category = category . to_s . prepare_category_name
396- raise StandardError , "No such category: #{ category } " unless @categories . include? ( category )
397-
398- reader = Streaming ::LineReader . new ( io , batch_size : batch_size )
399- total = reader . estimate_line_count
400- progress = Streaming ::Progress . new ( total : total )
401-
402- reader . each_batch do |batch |
403- synchronize do
404- batch . each do |text |
405- features = text . word_hash ( @min_word_length )
406- features . each_key { |word | @vocabulary [ word ] = true }
407- @training_data << { category : category , features : features }
408- end
409- @fitted = false
410- @dirty = true
411- end
412- progress . completed += batch . size
413- progress . current_batch += 1
414- yield progress if block_given?
393+ # @rbs (?(String | Symbol | nil), ?IO?, ?batch_size: Integer, **IO) { (Streaming::Progress) -> void } -> void
394+ def train_from_stream ( category = nil , io = nil , batch_size : Streaming ::DEFAULT_BATCH_SIZE , **categories , &)
395+ raise ArgumentError , 'Provide either (category, io) or keyword category: io pairs' if category . nil? && io . nil? && categories . empty?
396+ raise ArgumentError , 'Provide both category and io, or use keyword arguments' if [ category , io ] . one? ( &:nil? )
397+
398+ pairs = category && io ? { category => io } : categories
399+ pairs . each do |cat , stream |
400+ stream_train_category ( cat , stream , batch_size :, &)
415401 end
416402 end
417403
@@ -440,6 +426,33 @@ def train_batch(category = nil, documents = nil, batch_size: Streaming::DEFAULT_
440426
441427 private
442428
429+ # Trains from an IO stream with a single category.
430+ # @rbs (String | Symbol, IO, batch_size: Integer) { (Streaming::Progress) -> void } -> void
431+ def stream_train_category ( category , io , batch_size :)
432+ category = category . to_s . prepare_category_name
433+ raise ArgumentError , "No such category: #{ category } " unless @categories . include? ( category )
434+ raise ArgumentError , 'Stream must respond to #each_line' unless io . respond_to? ( :each_line )
435+
436+ reader = Streaming ::LineReader . new ( io , batch_size : batch_size )
437+ total = reader . estimate_line_count
438+ progress = Streaming ::Progress . new ( total : total )
439+
440+ reader . each_batch do |batch |
441+ synchronize do
442+ batch . each do |text |
443+ features = text . word_hash ( @min_word_length )
444+ features . each_key { |word | @vocabulary [ word ] = true }
445+ @training_data << { category : category , features : features }
446+ end
447+ @fitted = false
448+ @dirty = true
449+ end
450+ progress . completed += batch . size
451+ progress . current_batch += 1
452+ yield progress if block_given?
453+ end
454+ end
455+
443456 # Trains a batch of documents for a single category.
444457 # @rbs (String | Symbol, Array[String], ?batch_size: Integer) { (Streaming::Progress) -> void } -> void
445458 def train_batch_for_category ( category , documents , batch_size : Streaming ::DEFAULT_BATCH_SIZE )
0 commit comments