lib/torch/nn/functional.rb in torch-rb-0.3.6 vs lib/torch/nn/functional.rb in torch-rb-0.3.7

- old
+ new

@@ -467,10 +467,81 @@ def triplet_margin_loss(anchor, positive, negative, margin: 1.0, p: 2, eps: 1e-06, swap: false, reduction: "mean") Torch.triplet_margin_loss(anchor, positive, negative, margin, p, eps, swap, reduction) end + # vision + + def interpolate(input, size: nil, scale_factor: nil, mode: "nearest", align_corners: nil, recompute_scale_factor: nil) + if ["nearest", "area"].include?(mode) + unless align_corners.nil? + raise ArgumentError, "align_corners option can only be set with the interpolating modes: linear | bilinear | bicubic | trilinear" + end + else + if align_corners.nil? + align_corners = false + end + end + + scale_factor_len = input.dim - 2 + scale_factor_list = [nil] * scale_factor_len + # default value of recompute_scale_factor is False + if !scale_factor.nil? && (recompute_scale_factor == false || recompute_scale_factor.nil?) + if scale_factor.is_a?(Array) + _scale_factor_repeated = scale_factor + else + _scale_factor_repeated = [scale_factor] * scale_factor_len + end + scale_factor_list = _scale_factor_repeated + end + + # Give this variable a short name because it has to be repeated multiple times below. + sfl = scale_factor_list + + closed_over_args = [input, size, scale_factor, recompute_scale_factor] + output_size = _interp_output_size(closed_over_args) + if input.dim == 3 && mode == "nearest" + NN.upsample_nearest1d(input, output_size, sfl[0]) + elsif input.dim == 4 && mode == "nearest" + NN.upsample_nearest2d(input, output_size, sfl[0], sfl[1]) + elsif input.dim == 5 && mode == "nearest" + NN.upsample_nearest3d(input, output_size, sfl[0], sfl[1], sfl[2]) + elsif input.dim == 3 && mode == "area" + adaptive_avg_pool1d(input, output_size) + elsif input.dim == 4 && mode == "area" + adaptive_avg_pool2d(input, output_size) + elsif input.dim == 5 && mode == "area" + adaptive_avg_pool3d(input, output_size) + elsif input.dim == 3 && mode == "linear" + # assert align_corners is not None + NN.upsample_linear1d(input, output_size, align_corners, sfl[0]) + elsif input.dim == 3 && mode == "bilinear" + raise ArgumentError, "Got 3D input, but bilinear mode needs 4D input" + elsif input.dim == 3 && mode == "trilinear" + raise ArgumentError, "Got 3D input, but trilinear mode needs 5D input" + elsif input.dim == 4 && mode == "linear" + raise ArgumentError, "Got 4D input, but linear mode needs 3D input" + elsif input.dim == 4 && mode == "bilinear" + # assert align_corners is not None + NN.upsample_bilinear2d(input, output_size, align_corners, sfl[0], sfl[1]) + elsif input.dim == 4 && mode == "trilinear" + raise ArgumentError, "Got 4D input, but trilinear mode needs 5D input" + elsif input.dim == 5 && mode == "linear" + raise ArgumentError, "Got 5D input, but linear mode needs 3D input" + elsif input.dim == 5 && mode == "bilinear" + raise ArgumentError, "Got 5D input, but bilinear mode needs 4D input" + elsif input.dim == 5 && mode == "trilinear" + # assert align_corners is not None + NN.upsample_trilinear3d(input, output_size, align_corners, sfl[0], sfl[1], sfl[2]) + elsif input.dim == 4 && mode == "bicubic" + # assert align_corners is not None + NN.upsample_bicubic2d(input, output_size, align_corners, sfl[0], sfl[1]) + else + raise ArgumentError, "Input Error: Only 3D, 4D and 5D input Tensors supported (got #{input.dim}D) for the modes: nearest | linear | bilinear | bicubic | trilinear (got #{mode})" + end + end + private def softmax_dim(ndim) ndim == 0 || ndim == 1 || ndim == 3 ? 0 : 1 end @@ -481,9 +552,44 @@ elsif defaults.length < out_size.length raise ArgumentError, "Input dimension should be at least #{out_size.length + 1}" else out_size.zip(defaults.last(out_size.length)).map { |v, d| v || d } end + end + + def _interp_output_size(closed_over_args) + input, size, scale_factor, recompute_scale_factor = closed_over_args + dim = input.dim - 2 + if size.nil? && scale_factor.nil? + raise ArgumentError, "either size or scale_factor should be defined" + end + if !size.nil? && !scale_factor.nil? + raise ArgumentError, "only one of size or scale_factor should be defined" + end + if !scale_factor.nil? + if scale_factor.is_a?(Array) + if scale_factor.length != dim + raise ArgumentError, "scale_factor shape must match input shape. Input is #{dim}D, scale_factor size is #{scale_factor.length}" + end + end + end + + if !size.nil? + if size.is_a?(Array) + return size + else + return [size] * dim + end + end + + raise "Failed assertion" if scale_factor.nil? + if scale_factor.is_a?(Array) + scale_factors = scale_factor + else + scale_factors = [scale_factor] * dim + end + + dim.times.map { |i| (input.size(i + 2) * scale_factors[i]).floor } end end end # shortcut