func (scaler *StandardScaler) InverseTransform(X, Y *mat.Dense) (Xout, Yout *mat.Dense) {
	if X == nil {
		return X, Y
	}
	Xmat := X.RawMatrix()
	Xout = mat.NewDense(Xmat.Rows, Xmat.Cols, nil)
	Xoutmat := Xout.RawMatrix()
	for i := 0; i < Xmat.Cols; i++ {
		mean, scale := 0., 1.
		if scaler.WithMean {
			mean = scaler.Mean.At(0, i)
		}
		if scaler.WithStd {
			scale = scaler.Scale.At(0, i)
		}
		for jX, jXout := 0, 0; jX < Xmat.Rows*Xmat.Stride; jX, jXout = jX+Xmat.Stride, jXout+Xoutmat.Stride {
			Xoutmat.Data[jXout+i] = mean + Xmat.Data[jX+i]*scale
		}
	}
	return Xout, Y
}
InverseTransform unscales data
package preprocessing
import (
	"fmt"
	"math"
	"sort"
	"golang.org/x/exp/rand"
	"github.com/pa-m/sklearn/base"
	"github.com/pa-m/optimize"
	"gonum.org/v1/gonum/floats"
	"gonum.org/v1/gonum/mat"
	"gonum.org/v1/gonum/stat"
)
type float = float64
type Transformer = base.Transformer
type InverseTransformer interface {
	Transformer
	InverseTransform(X, Y *mat.Dense) (Xout, Yout *mat.Dense)
}
type MinMaxScaler struct {
	FeatureRange                            []float
	Scale, Min, DataMin, DataMax, DataRange *mat.Dense
	NSamplesSeen                            int
}
func NewMinMaxScaler(featureRange []float) *MinMaxScaler {
	return &MinMaxScaler{FeatureRange: featureRange}
}
func (scaler *MinMaxScaler) TransformerClone() base.Transformer {
	var clone = *scaler
	return &clone
}
func (scaler *MinMaxScaler) Reset() *MinMaxScaler {
	scaler.NSamplesSeen = 0
	return scaler
}
func (scaler *MinMaxScaler) Fit(X, Y mat.Matrix) base.Fiter {
	scaler.Reset()
	return scaler.PartialFit(X, Y)
}
func (scaler *MinMaxScaler) PartialFit(Xmatrix, Ymatrix mat.Matrix) Transformer {
	X := base.ToDense(Xmatrix)
	nSamples, nFeatures := X.Dims()
	if nSamples == 0 {
		return scaler
	}
	if scaler.NSamplesSeen == 0 {
		scaler.DataRange = mat.NewDense(1, nFeatures, nil)
		scaler.DataMin = mat.NewDense(1, nFeatures, nil)
		scaler.DataMax = mat.NewDense(1, nFeatures, nil)
		scaler.Min = mat.NewDense(1, nFeatures, nil)
		scaler.Scale = mat.NewDense(1, nFeatures, nil)
		scaler.DataMin.CloneFrom(X.RowView(0).T())
		scaler.DataMax.CloneFrom(X.RowView(0).T())
	}
	X.Apply(func(i int, j int, x float64) float64 {
		scaler.DataMin.Set(0, j, math.Min(scaler.DataMin.At(0, j), x))
		scaler.DataMax.Set(0, j, math.Max(scaler.DataMax.At(0, j), x))
		return x
	}, X)
	scaler.NSamplesSeen += nSamples
	scaler.DataRange.Sub(scaler.DataMax, scaler.DataMin)
	scaler.DataRange.Apply(func(i int, j int, x float64) float64 {
		if x == 0. {
			return 1.
		}
		return x
	}, scaler.DataRange)
	scaler.Scale.Apply(func(i int, j int, x float64) float64 {
		return (scaler.FeatureRange[1] - scaler.FeatureRange[0]) / x
	}, scaler.DataRange)
	scaler.Min.Apply(func(i int, j int, x float64) float64 {
		return scaler.FeatureRange[0] - scaler.DataMin.At(i, j)*scaler.Scale.At(i, j)
	}, scaler.DataRange)
	return scaler
}
func (scaler *MinMaxScaler) Transform(X, Y mat.Matrix) (Xout, Yout *mat.Dense) {
	nSamples, nFeatures := X.Dims()
	Xout = mat.NewDense(nSamples, nFeatures, nil)
	Xout.Apply(func(i int, j int, x float64) float64 {
		return scaler.Min.At(0, j) + x*scaler.Scale.At(0, j)
	}, X)
	return Xout, base.ToDense(Y)
}
func (scaler *MinMaxScaler) FitTransform(X, Y mat.Matrix) (Xout, Yout *mat.Dense) {
	scaler.Fit(X, Y)
	return scaler.Transform(X, Y)
}
func (scaler *MinMaxScaler) InverseTransform(X, Y *mat.Dense) (Xout, Yout *mat.Dense) {
	if X == nil {
		return X, Y
	}
	nSamples, nFeatures := X.Dims()
	Xout = mat.NewDense(nSamples, nFeatures, nil)
	Xout.Apply(func(i int, j int, x float64) float64 {
		return (x - scaler.Min.At(0, j)) / scaler.Scale.At(0, j)
	}, X)
	return Xout, Y
}
type StandardScaler struct {
	WithMean, WithStd bool
	Scale, Mean, Var  *mat.Dense
	NSamplesSeen      int
}
func NewStandardScaler() *StandardScaler {
	return &StandardScaler{WithMean: true, WithStd: true}
}
func (scaler *StandardScaler) TransformerClone() base.Transformer {
	var clone = *scaler
	return &clone
}
func (scaler *StandardScaler) Reset() *StandardScaler {
	scaler.NSamplesSeen = 0
	return scaler
}
func (scaler *StandardScaler) Fit(Xmatrix, Ymatrix mat.Matrix) base.Fiter {
	X, Y := base.ToDense(Xmatrix), base.ToDense(Ymatrix)
	scaler.Reset()
	return scaler.PartialFit(X, Y)
}
func (scaler *StandardScaler) PartialFit(X, Y *mat.Dense) Transformer {
	nSamples, nFeatures := X.Dims()
	if nSamples == 0 {
		return scaler
	}
	if scaler.NSamplesSeen == 0 {
		scaler.Var = mat.NewDense(1, nFeatures, nil)
		scaler.Mean = mat.NewDense(1, nFeatures, nil)
		scaler.Scale = mat.NewDense(1, nFeatures, nil)
	}
	scaler.Mean, scaler.Var, scaler.NSamplesSeen = IncrementalMeanAndVar(X, scaler.Mean, scaler.Var, scaler.NSamplesSeen)
	scaler.Scale.Apply(func(i int, j int, vj float64) float64 {
		if vj == 0. {
			vj = 1.
		}
		return math.Sqrt(vj)
	}, scaler.Var)
	return scaler
}
func (scaler *StandardScaler) Transform(X, Y mat.Matrix) (Xout, Yout *mat.Dense) {
	Xmat := base.ToDense(X).RawMatrix()
	Xout = mat.NewDense(Xmat.Rows, Xmat.Cols, nil)
	Xoutmat := Xout.RawMatrix()
	for i := 0; i < Xmat.Cols; i++ {
		mean, scale := 0., 1.
		if scaler.WithMean {
			mean = scaler.Mean.At(0, i)
		}
		if scaler.WithStd {
			scale = scaler.Scale.At(0, i)
		}
		for jX, jXout := 0, 0; jX < Xmat.Rows*Xmat.Stride; jX, jXout = jX+Xmat.Stride, jXout+Xoutmat.Stride {
			Xoutmat.Data[jXout+i] = (Xmat.Data[jX+i] - mean) / scale
		}
	}
	return Xout, base.ToDense(Y)
}
func (scaler *StandardScaler) FitTransform(X, Y mat.Matrix) (Xout, Yout *mat.Dense) {
	scaler.Fit(X, Y)
	return scaler.Transform(X, Y)
}