예제 #1
0
            protected override sealed void TransformCore(ref TInput input, FixedSizeQueue <TInput> windowedBuffer, long iteration, ref VBuffer <Double> dst)
            {
                var outputLength = Parent._outputLength;

                Host.Assert(outputLength >= 2);

                var result = dst.Values;

                if (Utils.Size(result) < outputLength)
                {
                    result = new Double[outputLength];
                }

                float rawScore = 0;

                for (int i = 0; i < outputLength; ++i)
                {
                    result[i] = Double.NaN;
                }

                // Step 1: Computing the raw anomaly score
                result[1] = ComputeRawAnomalyScore(ref input, windowedBuffer, iteration);

                if (Double.IsNaN(result[1]))
                {
                    result[0] = 0;
                }
                else
                {
                    if (WindowSize > 0)
                    {
                        // Step 2: Computing the p-value score
                        rawScore = (float)result[1];
                        if (Parent.ThresholdScore == AlertingScore.RawScore)
                        {
                            switch (Parent.Side)
                            {
                            case AnomalySide.Negative:
                                rawScore = (float)(-result[1]);
                                break;

                            case AnomalySide.Positive:
                                break;

                            default:
                                rawScore = (float)Math.Abs(result[1]);
                                break;
                            }
                        }
                        else
                        {
                            result[2] = ComputeKernelPValue(rawScore);

                            switch (Parent.Side)
                            {
                            case AnomalySide.Negative:
                                result[2] = 1 - result[2];
                                break;

                            case AnomalySide.Positive:
                                break;

                            default:
                                result[2] = Math.Min(result[2], 1 - result[2]);
                                break;
                            }

                            // Keeping the p-value in the safe range
                            if (result[2] < MinPValue)
                            {
                                result[2] = MinPValue;
                            }
                            else if (result[2] > MaxPValue)
                            {
                                result[2] = MaxPValue;
                            }

                            _rawScoreBuffer.AddLast(rawScore);

                            // Step 3: Computing the martingale value
                            if (Parent.Martingale != MartingaleType.None && Parent.ThresholdScore == AlertingScore.MartingaleScore)
                            {
                                Double martingaleUpdate = 0;
                                switch (Parent.Martingale)
                                {
                                case MartingaleType.Power:
                                    martingaleUpdate = Parent.LogPowerMartigaleBettingFunc(result[2], Parent.PowerMartingaleEpsilon);
                                    break;

                                case MartingaleType.Mixture:
                                    martingaleUpdate = Parent.LogMixtureMartigaleBettingFunc(result[2]);
                                    break;
                                }

                                if (_logMartingaleUpdateBuffer.Count == 0)
                                {
                                    for (int i = 0; i < _logMartingaleUpdateBuffer.Capacity; ++i)
                                    {
                                        _logMartingaleUpdateBuffer.AddLast(martingaleUpdate);
                                    }
                                    _logMartingaleValue += _logMartingaleUpdateBuffer.Capacity * martingaleUpdate;
                                }
                                else
                                {
                                    _logMartingaleValue += martingaleUpdate;
                                    _logMartingaleValue -= _logMartingaleUpdateBuffer.PeekFirst();
                                    _logMartingaleUpdateBuffer.AddLast(martingaleUpdate);
                                }

                                result[3] = Math.Exp(_logMartingaleValue);
                            }
                        }
                    }

                    // Generating alert
                    bool alert = false;

                    if (_rawScoreBuffer.IsFull) // No alert until the buffer is completely full.
                    {
                        switch (Parent.ThresholdScore)
                        {
                        case AlertingScore.RawScore:
                            alert = rawScore >= Parent.AlertThreshold;
                            break;

                        case AlertingScore.PValueScore:
                            alert = result[2] <= Parent.AlertThreshold;
                            break;

                        case AlertingScore.MartingaleScore:
                            alert = (Parent.Martingale != MartingaleType.None) && (result[3] >= Parent.AlertThreshold);

                            if (alert)
                            {
                                if (_martingaleAlertCounter > 0)
                                {
                                    alert = false;
                                }
                                else
                                {
                                    _martingaleAlertCounter = Parent.WindowSize;
                                }
                            }

                            _martingaleAlertCounter--;
                            _martingaleAlertCounter = _martingaleAlertCounter < 0 ? 0 : _martingaleAlertCounter;
                            break;
                        }
                    }

                    result[0] = Convert.ToDouble(alert);
                }

                dst = new VBuffer <Double>(outputLength, result, dst.Indices);
            }