Skip to content

Add Seasonality Detection #5200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions src/Microsoft.ML.TimeSeries/MathUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.ML.TimeSeries
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR doesn't integrate with any other code in ML.NET. How does this implement seasonality detection?
Can you please update it or close it if this is not going to be developed further?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will update it NLT tomorrow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review PR 5231 and I have asked the PR owner to abandon this PR.

internal class MathUtils
{
/// <summary>
/// use quick-sort like method to obtain the median value.
/// the complexity in expectation is O(n), which is faster than using quickSort.
/// </summary>
/// <param name="values">the input list of values. note that this list will be modified after calling this method</param>
/// <returns>returns the median value</returns>
public static double QuickMedian(List<double> values)
{
if (values == null || values.Count == 0)
return double.NaN;

// here the third parameter is start from 1. so we need to plus 1 to compliant.
return QuickSelect(values, values.Count / 2 + 1);
}

public static double QuickSelect(IReadOnlyList<double> values, int k)
{
var nums = values;
double[] left = new double[values.Count];
double[] right = new double[values.Count];
int numsCount = nums.Count;

while (true)
{
if (numsCount == 1)
return nums[0];

int idx = FindMedianIndex(nums, 0, numsCount - 1);
double key = nums[idx];

int leftIdx = 0;
int rightIdx = 0;
for (int i = 0; i < numsCount; i++)
{
if (i == idx)
continue;

if (nums[i] < key)
left[leftIdx++] = nums[i];
else
right[rightIdx++] = nums[i];
}

if (leftIdx == k - 1)
return key;

if (leftIdx >= k)
{
nums = left;
numsCount = leftIdx;
}
else
{
nums = right;
k = k - leftIdx - 1;
numsCount = rightIdx;
}
}
}

public static int FindMedianIndex(IReadOnlyList<double> values, int start, int end)
{
// use the middle value among first/middle/end as the guard value, to make sure the average performance good.
// according to unit test, this fix will improve the average performance 10%. and works normally when input list is ordered.
double first = values[start];
double last = values[end];
int midIndex = (start + end) / 2;
int medianIndex = -1;
double middleValue = values[midIndex];
if (first < last)
{
if (middleValue > last)
{
// last is the middle value
medianIndex = end;
}
else if (middleValue > first)
{
// middleValue is the middle value
medianIndex = midIndex;
}
else
{
// first is the middle value
medianIndex = start;
}
}
else
{
if (middleValue > first)
{
// first is the middle value
medianIndex = start;
}
else if (middleValue < last)
{
// last is the middle value
medianIndex = end;
}
else
{
// middleValue is the middle value
medianIndex = midIndex;
}
}
return medianIndex;
}
}
}
Loading