Browse Source

Correlation: cosmetics

ridge-regression
Christoph Ruegg 8 years ago
parent
commit
e666397f01
  1. 9
      .paket/Paket.Restore.targets
  2. 23
      src/Numerics.Tests/StatisticsTests/CorrelationTests.cs
  3. 116
      src/Numerics/Statistics/Correlation.cs

9
.paket/Paket.Restore.targets

@ -71,7 +71,10 @@
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '$(PaketRestoreCachedHash)' ">false</PaketRestoreRequired>
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '' ">true</PaketRestoreRequired>
</PropertyGroup>
<PropertyGroup Condition="'$(PaketPropsVersion)' != '5.174.2' ">
<PaketRestoreRequired>true</PaketRestoreRequired>
</PropertyGroup>
<!-- Do a global restore if required -->
<Exec Command='$(PaketBootStrapperCommand)' Condition="Exists('$(PaketBootStrapperExePath)') AND !(Exists('$(PaketExePath)'))" ContinueOnError="false" />
@ -132,11 +135,11 @@
<Error Condition=" '$(DoAllResolvedFilesExist)' != 'true' AND '$(ResolveNuGetPackages)' != 'False' " Text="One Paket file '@(PaketResolvedFilePaths)' is missing while restoring $(MSBuildProjectFile). Please delete 'paket-files/paket.restore.cached' and call 'paket restore'." />
<!-- Step 4 forward all msbuild properties (PackageReference, DotNetCliToolReference) to msbuild -->
<ReadLinesFromFile Condition="'@(PaketResolvedFilePaths)' != ''" File="%(PaketResolvedFilePaths.Identity)" ><!--Condition="Exists('%(PaketResolvedFilePaths.Identity)')"-->
<ReadLinesFromFile Condition="($(DesignTimeBuild) != true OR '$(PaketPropsLoaded)' != 'true') AND '@(PaketResolvedFilePaths)' != ''" File="%(PaketResolvedFilePaths.Identity)" >
<Output TaskParameter="Lines" ItemName="PaketReferencesFileLines"/>
</ReadLinesFromFile>
<ItemGroup Condition=" '@(PaketReferencesFileLines)' != '' " >
<ItemGroup Condition="($(DesignTimeBuild) != true OR '$(PaketPropsLoaded)' != 'true') AND '@(PaketReferencesFileLines)' != '' " >
<PaketReferencesFileLinesInfo Include="@(PaketReferencesFileLines)" >
<PackageName>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])</PackageName>
<PackageVersion>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])</PackageVersion>

23
src/Numerics.Tests/StatisticsTests/CorrelationTests.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2016 Math.NET
// Copyright (c) 2009-2018 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -32,8 +32,6 @@ using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using MathNet.Numerics.Statistics;
using MathNet.Numerics.LinearAlgebra.Double;
using System.IO;
using MathNet.Numerics.TestData;
using System.Globalization;
@ -67,24 +65,23 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
[TestCase("numpy.CorrNumpyData_pwm.csv", 0.005)]
[TestCase("numpy.CorrNumpyData_sin.csv", 0.005)]
[TestCase("numpy.CorrNumpyData_rnd.csv", 0.005)]
public void TestAutocorrelation(string fName, double tol)
public void AutoCorrelationTest(string fName, double tol)
{
var data = Data.ReadAllLines(fName)
.Select(line =>
{
var vals = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return new Tuple<string, string>(vals[0], vals[1]);
}).ToArray();
.Select(line =>
{
var vals = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return new Tuple<string, string>(vals[0], vals[1]);
}).ToArray();
var series = data.Select(tuple => Double.Parse(tuple.Item1, CultureInfo.InvariantCulture)).ToArray();
var resNumpy = data.Select(tuple => Double.Parse(tuple.Item2, CultureInfo.InvariantCulture)).ToArray();
var resMathNet = Statistics.Correlation.AutoCorrelation(series);
var resMathNet = Correlation.Auto(series);
for (int i = 0; i < resMathNet.Length; i++)
{
Assert.AreEqual(resNumpy[i], resMathNet[i], tol);
}
}
/// <summary>

116
src/Numerics/Statistics/Correlation.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2014 Math.NET
// Copyright (c) 2009-2018 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -42,81 +42,88 @@ namespace MathNet.Numerics.Statistics
/// </summary>
public static class Correlation
{
/// <summary>
/// autocorrelation function (ACF) based on fft (usually faster then direct brute force implementation) for all possible lags k
/// First element is hidden since ACF(k = 0) = 1 </summary>
/// <param name="x"> data array to calculate auto correlation for</param>
/// <returns>an array with the ACF as a function of the lags k</returns>
public static double[] AutoCorrelation(IEnumerable<double> x)
/// <summary>
/// Autocorrelation function (ACF) based on FFT for all possible lags k.
/// The first element is hidden since ACF(k = 0) = 1.
/// </summary>
/// <param name="x">Data array to calculate auto correlation for.</param>
/// <returns>An array with the ACF as a function of the lags k.</returns>
public static double[] Auto(IEnumerable<double> x)
{
return autoCorrelationFft(x, 0, x.Count() - 1);
return AutoCorrelationFft(x, 0, x.Count() - 1);
}
/// <summary>
/// autocorrelation function (ACF) based on fft (usually faster then direct brute force implementation) for lags
/// between kMin and kMax
/// First element is hidden since ACF(k = 0) = 1 </summary>
/// <param name="x"> the data array to calculate auto correlation for</param>
/// <param name="kMax"> max lag to calculate ACF for must be positive and smaller than x.Length-1</param>
/// <param name="kMin"> min lag to calculate ACF for (0 = no shift with acf=1) must be zero or positive and smaller than x.Length-1</param>
/// <returns>an array with the ACF as a function of the lags k</returns>
public static double[] AutoCorrelation(IEnumerable<double> x, int kMax, int kMin = 0)
/// <summary>
/// Autocorrelation function (ACF) based on FFT for lags between kMin and kMax.
/// The first element is hidden since ACF(k = 0) = 1.
/// </summary>
/// <param name="x">The data array to calculate auto correlation for.</param>
/// <param name="kMax">Max lag to calculate ACF for must be positive and smaller than x.Length-1.</param>
/// <param name="kMin">Min lag to calculate ACF for (0 = no shift with acf=1) must be zero or positive and smaller than x.Length-1.</param>
/// <returns>An array with the ACF as a function of the lags k.</returns>
public static double[] Auto(IEnumerable<double> x, int kMax, int kMin = 0)
{
// assert max and min in proper order
var kMax2 = Math.Max(kMax, kMin);
var kMin2 = Math.Min(kMax, kMin);
return (autoCorrelationFft(x, kMin2, kMax2));
return AutoCorrelationFft(x, kMin2, kMax2);
}
/// <summary>
/// autocorrelation function based on fft for lags k (faster than brute force calculation for big sample sizes).
/// First element is skipped since ACF(k = 0) = 1 </summary>
/// <param name="x"> the data array to calculate auto correlation for</param>
/// <param name="k"> array with lags to calculate ACF for</param>
/// <returns>an array with the ACF as a function of the lags k</returns>
public static double[] AutoCorrelation(IEnumerable<double> x, int[] k)
/// <summary>
/// Autocorrelation function based on FFT for lags k.
/// The first element is hidden since ACF(k = 0) = 1.
/// </summary>
/// <param name="x">The data array to calculate auto correlation for.</param>
/// <param name="k">Array with lags to calculate ACF for.</param>
/// <returns>An array with the ACF as a function of the lags k.</returns>
public static double[] Auto(IEnumerable<double> x, int[] k)
{
if (k == null)
throw new ArgumentNullException("k");
{
throw new ArgumentNullException(nameof(k));
}
if (k.Length < 1)
{
throw new ArgumentException("k");
}
// get acf between full range
var acf = autoCorrelationFft(x, k.Min(), k.Max());
var acf = AutoCorrelationFft(x, k.Min(), k.Max());
// map output by indexing
var acfReturn = new double[k.Length];
for (int i = 0; i < acfReturn.Length; i++)
acfReturn[i] = acf[k[i]];
var result = new double[k.Length];
for (int i = 0; i < result.Length; i++)
{
result[i] = acf[k[i]];
}
return acfReturn;
return result;
}
/// <summary>
/// this is the internal core method for calculating the autocorrelation
/// The internal core method for calculating the autocorrelation.
/// </summary>
/// <param name="x">the data array to calculate auto correlation for</param>
/// <param name="k_low"> min lag to calculate ACF for (0 = no shift with acf=1) must be zero or positive and smaller than x.Length-1</param>
/// <param name="k_high"> max lag to calculate ACF for must be positive and smaller than x.Length-1</param>
/// <returns>an array with the ACF as a function of the lags k</returns>
private static double[] autoCorrelationFft(IEnumerable<double> x, int k_low, int k_high)
/// <param name="x">The data array to calculate auto correlation for</param>
/// <param name="k_low">Min lag to calculate ACF for (0 = no shift with acf=1) must be zero or positive and smaller than x.Length-1</param>
/// <param name="k_high">Max lag to calculate ACF for must be positive and smaller than x.Length-1</param>
/// <returns>An array with the ACF as a function of the lags k.</returns>
private static double[] AutoCorrelationFft(IEnumerable<double> x, int k_low, int k_high)
{
if (x == null)
throw new ArgumentNullException("x");
throw new ArgumentNullException(nameof(x));
if (k_low < 0 || k_low >= x.Count())
throw new ArgumentOutOfRangeException("kMin must be zero or positive and smaller than x.Length");
if (k_high < 0 || k_high >= x.Count())
throw new ArgumentOutOfRangeException("kMax must be positive and smaller than x.Length");
int N = x.Count(); // Sample size
if (k_low < 0 || k_low >= N)
throw new ArgumentOutOfRangeException(nameof(k_low), "kMin must be zero or positive and smaller than x.Length");
if (k_high < 0 || k_high >= N)
throw new ArgumentOutOfRangeException(nameof(k_high), "kMax must be positive and smaller than x.Length");
if (x.Count() < 1)
if (N < 1)
return new double[0];
int N = x.Count(); // Sample size
int nFFT = Euclid.CeilingToPowerOfTwo(N) * 2;
Complex[] x_fft = new Complex[nFFT];
@ -133,7 +140,7 @@ namespace MathNet.Numerics.Statistics
if (ii < N)
{
if (!iex.MoveNext())
throw new ArgumentOutOfRangeException("x");
throw new ArgumentOutOfRangeException(nameof(x));
xArrNow = iex.Current;
x_fft[ii] = new Complex(xArrNow - x_dash, 0.0); // copy values in range and substract mean
}
@ -152,6 +159,7 @@ namespace MathNet.Numerics.Statistics
}
Fourier.Inverse(x_fft2, FourierOptions.Matlab);
double acf_Val1 = x_fft2[0].Real;
double[] acf_Vec = new double[k_high - k_low];
@ -163,7 +171,7 @@ namespace MathNet.Numerics.Statistics
acf_Vec[ii] = x_fft2[k_low + ii + 1].Real / acf_Val1;
}
return (acf_Vec);
return acf_Vec;
}
/// <summary>
@ -192,7 +200,7 @@ namespace MathNet.Numerics.Statistics
{
if (!ieB.MoveNext())
{
throw new ArgumentOutOfRangeException("dataB", Resources.ArgumentArraysSameLength);
throw new ArgumentOutOfRangeException(nameof(dataB), Resources.ArgumentArraysSameLength);
}
double currentA = ieA.Current;
@ -214,7 +222,7 @@ namespace MathNet.Numerics.Statistics
if (ieB.MoveNext())
{
throw new ArgumentOutOfRangeException("dataA", Resources.ArgumentArraysSameLength);
throw new ArgumentOutOfRangeException(nameof(dataA), Resources.ArgumentArraysSameLength);
}
}
@ -248,11 +256,11 @@ namespace MathNet.Numerics.Statistics
{
if (!ieB.MoveNext())
{
throw new ArgumentOutOfRangeException("dataB", Resources.ArgumentArraysSameLength);
throw new ArgumentOutOfRangeException(nameof(dataB), Resources.ArgumentArraysSameLength);
}
if (!ieW.MoveNext())
{
throw new ArgumentOutOfRangeException("weights", Resources.ArgumentArraysSameLength);
throw new ArgumentOutOfRangeException(nameof(weights), Resources.ArgumentArraysSameLength);
}
++n;
@ -277,11 +285,11 @@ namespace MathNet.Numerics.Statistics
}
if (ieB.MoveNext())
{
throw new ArgumentOutOfRangeException("dataB", Resources.ArgumentArraysSameLength);
throw new ArgumentOutOfRangeException(nameof(dataB), Resources.ArgumentArraysSameLength);
}
if (ieW.MoveNext())
{
throw new ArgumentOutOfRangeException("weights", Resources.ArgumentArraysSameLength);
throw new ArgumentOutOfRangeException(nameof(weights), Resources.ArgumentArraysSameLength);
}
}
return covariance/Math.Sqrt(varA*varB);

Loading…
Cancel
Save