Documentation ¶
Index ¶
- Variables
- func FunctionPeriodicAnomalyMaker(name string, model function.MetricFunction) function.MetricFunction
- func Linear(ys []float64) []float64
- func LinearRegression(ys []float64) (float64, float64)
- func RollingMultiplicativeHoltWinters(ys []float64, period int, levelLearningRate float64, trendLearningRate float64, ...) []float64
- func RollingSeasonal(ys []float64, period int, seasonalLearningRate float64) []float64
Constants ¶
This section is empty.
Variables ¶
var FunctionAnomalyRollingMultiplicativeHoltWinters = FunctionPeriodicAnomalyMaker("forecast.anomaly_rolling_multiplicative_holt_winters", FunctionRollingMultiplicativeHoltWinters)
var FunctionAnomalyRollingSeasonal = FunctionPeriodicAnomalyMaker("forecast.anomaly_rolling_seasonal", FunctionRollingSeasonal)
var FunctionDrop = function.MakeFunction( "forecast.drop", func(timerange api.Timerange, original api.SeriesList, dropTime time.Duration) api.SeriesList { lastValue := float64(timerange.Slots()) - dropTime.Seconds()/timerange.Resolution().Seconds() result := make([]api.Timeseries, len(original.Series)) for i, series := range original.Series { values := make([]float64, len(series.Values)) result[i] = series for j := range values { if float64(j) < lastValue { values[j] = series.Values[j] } else { values[j] = math.NaN() } } result[i].Values = values } return api.SeriesList{ Series: result, } }, )
var FunctionLinear = function.MakeFunction( "forecast.linear", func(context function.EvaluationContext, seriesExpression function.Expression, optionalTrainingTime *time.Duration) (api.SeriesList, error) { extraTrainingTime := time.Duration(0) if optionalTrainingTime != nil { extraTrainingTime = *optionalTrainingTime } if extraTrainingTime < 0 { return api.SeriesList{}, fmt.Errorf("extra training time must be non-negative, but got %s", extraTrainingTime.String()) } newContext := context.WithTimerange(context.Timerange().ExtendBefore(extraTrainingTime)) extraSlots := newContext.Timerange().Slots() - context.Timerange().Slots() seriesList, err := function.EvaluateToSeriesList(seriesExpression, newContext) if err != nil { return api.SeriesList{}, err } result := api.SeriesList{ Series: make([]api.Timeseries, len(seriesList.Series)), } for seriesIndex, series := range seriesList.Series { result.Series[seriesIndex] = api.Timeseries{ TagSet: series.TagSet, Values: Linear(series.Values)[extraSlots:], } } return result, nil }, function.Option{Name: function.WidenBy, Value: function.Argument(1)}, )
FunctionLinear forecasts with a simple linear regression. For data which is mostly just a linear trend up or down, this will provide a good model of current behavior, as well as a good estimate of near-future behavior.
var FunctionRollingMultiplicativeHoltWinters = function.MakeFunction( "forecast.rolling_multiplicative_holt_winters", func(context function.EvaluationContext, seriesExpression function.Expression, period time.Duration, levelLearningRate float64, trendLearningRate float64, seasonalLearningRate float64, optionalExtraTrainingTime *time.Duration) (api.SeriesList, error) { extraTrainingTime := time.Duration(0) if optionalExtraTrainingTime != nil { extraTrainingTime = *optionalExtraTrainingTime } if extraTrainingTime < 0 { return api.SeriesList{}, fmt.Errorf("extra training time must be non-negative, but got %s", extraTrainingTime.String()) } samples := int(period / context.Timerange().Resolution()) if samples <= 0 { return api.SeriesList{}, fmt.Errorf("forecast.rolling_multiplicative_holt_winters expects the period parameter to mean at least one slot") } newContext := context.WithTimerange(context.Timerange().ExtendBefore(extraTrainingTime)) extraSlots := newContext.Timerange().Slots() - context.Timerange().Slots() seriesList, err := function.EvaluateToSeriesList(seriesExpression, newContext) if err != nil { return api.SeriesList{}, err } result := api.SeriesList{ Series: make([]api.Timeseries, len(seriesList.Series)), } for seriesIndex, series := range seriesList.Series { result.Series[seriesIndex] = api.Timeseries{ TagSet: series.TagSet, Values: RollingMultiplicativeHoltWinters(series.Values, samples, levelLearningRate, trendLearningRate, seasonalLearningRate)[extraSlots:], } } return result, nil }, function.Option{Name: function.WidenBy, Value: function.Argument(5)}, )
FunctionRollingMultiplicativeHoltWinters computes a rolling multiplicative Holt-Winters model for the data. It takes in several learning rates, as well as the period that describes the periodicity of the seasonal term. The learning rates are interpreted as being "per period." For example, a value of 0.5 means that values in this period are effectively weighted twice as much as those in the previous. A value of 0.9 means that values in this period are weighted 1.0/(1.0 - 0.9) = 10 times as much as the previous.
var FunctionRollingSeasonal = function.MakeFunction( "forecast.rolling_seasonal", func(context function.EvaluationContext, seriesExpression function.Expression, period time.Duration, seasonalLearningRate float64, optionalExtraTrainingTime *time.Duration) (api.SeriesList, error) { extraTrainingTime := time.Duration(0) if optionalExtraTrainingTime != nil { extraTrainingTime = *optionalExtraTrainingTime } if extraTrainingTime < 0 { return api.SeriesList{}, fmt.Errorf("extra training time must be non-negative, but got %s", extraTrainingTime.String()) } samples := int(period / context.Timerange().Resolution()) if samples <= 0 { return api.SeriesList{}, fmt.Errorf("forecast.rolling_seasonal expects the period parameter to mean at least one slot") } newContext := context.WithTimerange(context.Timerange().ExtendBefore(extraTrainingTime)) extraSlots := newContext.Timerange().Slots() - context.Timerange().Slots() seriesList, err := function.EvaluateToSeriesList(seriesExpression, newContext) if err != nil { return api.SeriesList{}, err } result := api.SeriesList{ Series: make([]api.Timeseries, len(seriesList.Series)), } for seriesIndex, series := range seriesList.Series { result.Series[seriesIndex] = api.Timeseries{ TagSet: series.TagSet, Values: RollingSeasonal(series.Values, samples, seasonalLearningRate)[extraSlots:], } } return result, nil }, function.Option{Name: function.WidenBy, Value: function.Argument(3)}, )
FunctionRollingSeasonal is a forecasting MetricFunction that performs the rolling seasonal estimation. It is designed for data which shows seasonality without trends, although which a high learning rate it can perform tolerably well on data with trends as well.
Functions ¶
func FunctionPeriodicAnomalyMaker ¶
func FunctionPeriodicAnomalyMaker(name string, model function.MetricFunction) function.MetricFunction
FunctionPeriodicAnomalyMaker makes anomaly-measurement functions that return simple p-values for deviations from the predicted model. In order to make this procedure mostly automatic, it performs a join on the original tagsets to match them up with their predictions.
func LinearRegression ¶
LinearRegression estimates ys as (a + b*t) and returns (a, b). It performs linear regression using the explicit form for minimization of least-squares error. When ys[i] is NaN, it is treated as a missing point. (This makes things only slightly more complicated).
func RollingMultiplicativeHoltWinters ¶
func RollingMultiplicativeHoltWinters(ys []float64, period int, levelLearningRate float64, trendLearningRate float64, seasonalLearningRate float64) []float64
RollingMultiplicativeHoltWinters approximate the given input using the Holt-Winters model by performing exponential averaging on the HW parameters. It scales 'levelLearningRate' and 'trendLearningRate' by the 'period'. That is, if you double the period, it will take twice as long as before for the level and trend parameters to update. This makes it easier to use with varying period values.
func RollingSeasonal ¶
RollingSeasonal estimates purely seasonal data without a trend or level component. For data which shows no long- or short-term trends, this model is more likely to recognize deviant behavior. However, it will perform worse than Holt-Winters on data which does have any significant trends.
Types ¶
This section is empty.