You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: logistic_regression.rb
    path of file: ./repos/rumale/rumale-linear_model/lib/rumale/linear_model
    
    the code of the file until where you have to start completion: # frozen_string_literal: true

require 'lbfgsb'

require 'rumale/utils'
require 'rumale/validation'
require 'rumale/base/classifier'

require_relative 'base_estimator'

module Rumale
  module LinearModel
    # LogisticRegression is a class that implements (multinomial) Logistic Regression.
    #
    # @note
    #   Rumale::SVM provides Logistic Regression based on LIBLINEAR.
    #   If you prefer execution speed, you should use Rumale::SVM::LogisticRegression.
    #   https://github.com/yoshoku/rumale-svm
    #
    # @example
    #   require 'rumale/linear_model/logistic_regression'
    #
    #   estimator = Rumale::LinearModel::LogisticRegression.new(reg_param: 1.0)
    #   estimator.fit(training_samples, traininig_labels)
    #   results = estimator.predict(testing_samples)
    class LogisticRegression < Rumale::LinearModel::BaseEstimator
      include Rumale::Base::Classifier

      # Return the class labels.
      # @return [Numo::Int32] (shape: [n_classes])
      attr_reader :classes

      # Create a new classifier with Logisitc Regression.
      #
      # @param reg_param [Float] The regularization parameter.
      # @param fit_bias [Boolean] The flag indicating whether to fit the bias term.
      # @param bias_scale [Float] The scale of the bias term.
      #   If fit_bias is true, the feat
    
      def partial_fit(base_x, base_y) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
        if multiclass_problem?
          fnc = proc do |w, x, y, a|
            n_features = x.shape[1]
            n_classes = y.shape[1]
            z = x.dot(w.reshape(n_classes, n_features).transpose)
            # logsumexp and softmax
            z_max = z.max(-1).expand_dims(-1).dup
            z_max[~z_max.isfinite] = 0.0
            lgsexp = Numo::NMath.log(Numo::NMath.exp(z - z_max).sum(axis: -1)).expand_dims(-1) + z_max
            t = z - lgsexp
            sftmax = Numo::NMath.exp(t)
            # loss and gradient
            loss = -(y * t).sum + 0.5 * a * w.dot(w)
            grad = (sftmax - y).transpose.dot(x).flatten.dup + a * w
            [loss, grad]
          end

          base_x = expand_feature(base_x) if fit_bias?
          onehot_y = ::Rumale::Utils.binarize_labels(base_y)
          n_classes = @classes.size
          n_features = base_x.shape[1]
          w_init = Numo::DFloat.zeros(n_classes * n_features)

          res = Lbfgsb.minimize(
            fnc: fnc, jcb: true, x_init: w_init, args: [base_x, onehot_y, @params[:reg_param]],
            maxiter: @params[:max_iter], factr: @params[:tol] / Lbfgsb::DBL_EPSILON,
            verbose: @params[:verbose] ? 1 : -1
          )

          split_weight(res[:x].reshape(n_classes, n_features))
        else
          fnc = proc do |w, x, y, a|
            z = 1 + Numo::NMath.exp(-y * x.dot(w))
            loss = Numo::NMath.log(z).sum + 0.5 * a * w.dot(w)
            grad = (y / z - y).dot(x) + a * w
            [loss, grad]
          end

          base_x = expand_feature(base_x) if fit_bias?
          negative_label = @classes[0]
          bin_y = Numo::Int32.cast(base_y.ne(negative_label)) * 2 - 1
          n_features = base_x.shape[1]
          w_init = Numo::DFloat.zeros(n_features)

          res = Lbfgsb.minimize(
            fnc: fnc, jcb: true, x_init: w_init, args: [base_x, bin_y, @params[:reg_param]],
            maxiter: @params[:max_iter], factr: @params[:tol] / Lbfgsb::DBL_EPSILON,
            verbose: @params[:verbose] ? 1 : -1
          )

          split_weight(res[:x])
        end