Example #1
0
func testDerivParam(t *testing.T, d derivParamTester) {
	// Tests that the derivative matches for a number of different quantiles
	// along the distribution.
	nTest := 10
	quantiles := make([]float64, nTest)
	floats.Span(quantiles, 0.1, 0.9)

	deriv := make([]float64, d.NumParameters())
	fdDeriv := make([]float64, d.NumParameters())

	initParams := d.parameters(nil)
	init := make([]float64, d.NumParameters())
	for i, v := range initParams {
		init[i] = v.Value
	}
	for _, v := range quantiles {
		d.setParameters(initParams)
		x := d.Quantile(v)
		d.DLogProbDParam(x, deriv)
		f := func(p []float64) float64 {
			params := d.parameters(nil)
			for i, v := range p {
				params[i].Value = v
			}
			d.setParameters(params)
			return d.LogProb(x)
		}
		fd.Gradient(fdDeriv, f, init, nil)
		if !floats.EqualApprox(deriv, fdDeriv, 1e-6) {
			t.Fatal("Derivative mismatch. Want", fdDeriv, ", got", deriv, ".")
		}
	}
}
Example #2
0
func ExampleHistogram() {
	x := make([]float64, 101)
	for i := range x {
		x[i] = 1.1 * float64(i) // x data ranges from 0 to 110
	}
	dividers := []float64{7, 20, 100, 1000}
	fmt.Println(`Histogram counts the amount of data in the bins specified by
the dividers. In this data set, there are 7 data points less than 7 (dividers[0]),
12 data points between 7 and 20 (dividers[2] and dividers[1]), and 0 data points
above 1000. Since dividers has length 4, there will be 5 bins.`)
	hist := Histogram(nil, dividers, x, nil)
	fmt.Printf("Hist = %v\n", hist)

	fmt.Println()
	fmt.Println("For ease, the floats Span function can be used to set the dividers")
	nBins := 10
	// Create one fewer divider than bins, but add two to work with Span (see
	// note below)
	dividers = make([]float64, nBins+1)
	min, _ := floats.Min(x)
	max, _ := floats.Max(x)
	floats.Span(dividers, min, max)
	// Span includes the min and the max. Trim the dividers to create 10 buckets
	dividers = dividers[1 : len(dividers)-1]
	fmt.Println("len dividers = ", len(dividers))
	hist = Histogram(nil, dividers, x, nil)
	fmt.Printf("Hist = %v\n", hist)
	fmt.Println()
	fmt.Println(`Histogram also works with weighted data, and allows reusing of
the count field in order to avoid extra garbage`)
	weights := make([]float64, len(x))
	for i := range weights {
		weights[i] = float64(i + 1)
	}
	Histogram(hist, dividers, x, weights)
	fmt.Printf("Weighted Hist = %v\n", hist)

	// Output:
	// Histogram counts the amount of data in the bins specified by
	// the dividers. In this data set, there are 7 data points less than 7 (dividers[0]),
	// 12 data points between 7 and 20 (dividers[2] and dividers[1]), and 0 data points
	// above 1000. Since dividers has length 4, there will be 5 bins.
	// Hist = [7 12 72 10 0]
	//
	// For ease, the floats Span function can be used to set the dividers
	// len dividers =  9
	// Hist = [11 10 10 10 9 11 10 10 9 11]
	//
	// Histogram also works with weighted data, and allows reusing of
	// the count field in order to avoid extra garbage
	// Weighted Hist = [77 175 275 375 423 627 675 775 783 1067]
}
Example #3
0
func ExampleHistogram() {
	x := make([]float64, 101)
	for i := range x {
		x[i] = 1.1 * float64(i) // x data ranges from 0 to 110
	}
	dividers := []float64{0, 7, 20, 100, 1000}
	fmt.Println(`Histogram counts the amount of data in the bins specified by
the dividers. In this data set, there are 7 data points less than 7 (between dividers[0]
and dividers[1]), 12 data points between 7 and 20 (dividers[1] and dividers[2]),
and 0 data points above 1000. Since dividers has length 5, there will be 4 bins.`)
	hist := Histogram(nil, dividers, x, nil)
	fmt.Printf("Hist = %v\n", hist)

	fmt.Println()
	fmt.Println("For ease, the floats Span function can be used to set the dividers")
	nBins := 10
	dividers = make([]float64, nBins+1)
	min := floats.Min(x)
	max := floats.Max(x)
	// Increase the maximum divider so that the maximum value of x is contained
	// within the last bucket.
	max += 1
	floats.Span(dividers, min, max)
	// Span includes the min and the max. Trim the dividers to create 10 buckets
	hist = Histogram(nil, dividers, x, nil)
	fmt.Printf("Hist = %v\n", hist)
	fmt.Println()
	fmt.Println(`Histogram also works with weighted data, and allows reusing of
the count field in order to avoid extra garbage`)
	weights := make([]float64, len(x))
	for i := range weights {
		weights[i] = float64(i + 1)
	}
	Histogram(hist, dividers, x, weights)
	fmt.Printf("Weighted Hist = %v\n", hist)

	// Output:
	// Histogram counts the amount of data in the bins specified by
	// the dividers. In this data set, there are 7 data points less than 7 (between dividers[0]
	// and dividers[1]), 12 data points between 7 and 20 (dividers[1] and dividers[2]),
	// and 0 data points above 1000. Since dividers has length 5, there will be 4 bins.
	// Hist = [7 12 72 10]
	//
	// For ease, the floats Span function can be used to set the dividers
	// Hist = [11 10 10 10 10 10 10 10 10 10]
	//
	// Histogram also works with weighted data, and allows reusing of
	// the count field in order to avoid extra garbage
	// Weighted Hist = [66 165 265 365 465 565 665 765 865 965]
}
Example #4
0
func ExampleSingle() {
	fmt.Println("Create a grid using Span")
	grid := make([]float64, 3)
	floats.Span(grid, 0, 1)
	fmt.Println("grid =", grid)
	pts := meshgrid.Single(3, grid)
	fmt.Println("Generated points:")
	for _, v := range pts {
		fmt.Println(v)
	}
	// Output:
	// Create a grid using Span
	// grid = [0 0.5 1]
	// Generated points:
	// [0 0 0]
	// [0 0 0.5]
	// [0 0 1]
	// [0 0.5 0]
	// [0 0.5 0.5]
	// [0 0.5 1]
	// [0 1 0]
	// [0 1 0.5]
	// [0 1 1]
	// [0.5 0 0]
	// [0.5 0 0.5]
	// [0.5 0 1]
	// [0.5 0.5 0]
	// [0.5 0.5 0.5]
	// [0.5 0.5 1]
	// [0.5 1 0]
	// [0.5 1 0.5]
	// [0.5 1 1]
	// [1 0 0]
	// [1 0 0.5]
	// [1 0 1]
	// [1 0.5 0]
	// [1 0.5 0.5]
	// [1 0.5 1]
	// [1 1 0]
	// [1 1 0.5]
	// [1 1 1]
}
Example #5
0
// checkProbQuantContinuous checks that the Prob, Rand, and Quantile are all consistent.
// checkProbContinuous only checks that Prob is a valid distribution (integrates
// to 1 and greater than 0). However, this is also true if the PDF of a different
// distribution is used. This checks that PDF is also consistent with the
// CDF implementation and the random samples.
func checkProbQuantContinuous(t *testing.T, i int, xs []float64, c cumulantProber, tol float64) {
	ps := make([]float64, 101)
	floats.Span(ps, 0, 1)

	var xp, x float64
	for i, p := range ps {
		x = c.Quantile(p)
		if p == 0 {
			xp = x
			if floats.Min(xs) < x {
				t.Errorf("Sample of x less than Quantile(0). Case %v.", i)
				break
			}
			continue
		}
		if p == 1 {
			if floats.Max(xs) > x {
				t.Errorf("Sample of x greater than Quantile(1). Case %v.", i)
				break
			}
		}

		// The integral of the PDF between xp and x should be the difference in
		// the quantiles.
		q := quad.Fixed(c.Prob, xp, x, 1000, nil, 0)
		if math.Abs(q-(p-ps[i-1])) > 1e-10 {
			t.Errorf("Integral of PDF doesn't match quantile. Case %v. Want %v, got %v.", i, p-ps[i-1], q)
			break
		}

		pEst := stat.CDF(x, stat.Empirical, xs, nil)
		if math.Abs(pEst-p) > tol {
			t.Errorf("Empirical CDF doesn't match quantile. Case %v.", i)
		}
		xp = x
	}
}
Example #6
0
// testFullDist tests all of the functions of a fullDist.
func testFullDist(t *testing.T, f fullDist, i int) {
	tol := 1e-1
	const n = 1e6
	xs := make([]float64, n)
	for i := range xs {
		xs[i] = f.Rand()
	}
	sortedXs := make([]float64, n)
	copy(sortedXs, xs)
	sort.Float64s(sortedXs)
	tmp := make([]float64, n)

	// Mean check.
	mean := stat.Mean(xs, nil)
	if !floats.EqualWithinAbsOrRel(mean, f.Mean(), tol, tol) {
		t.Errorf("Mean mismatch case %v: want: %v, got: %v", i, mean, f.Mean())
	} else {
		mean = f.Mean()
	}

	// Median check.
	median := stat.Quantile(0.5, stat.Empirical, sortedXs, nil)
	if !floats.EqualWithinAbsOrRel(median, f.Median(), tol, tol) {
		t.Errorf("Median mismatch case %v: want: %v, got: %v", i, median, f.Median())
	}

	// Variance check.
	variance := stat.Variance(xs, nil)
	if !floats.EqualWithinAbsOrRel(variance, f.Variance(), tol, tol) {
		t.Errorf("Variance mismatch case %v: want: %v, got: %v", i, mean, f.Variance())
	} else {
		variance = f.Variance()
	}

	std := math.Sqrt(variance)
	if !floats.EqualWithinAbsOrRel(std, f.StdDev(), tol, tol) {
		t.Errorf("StdDev mismatch case %v: want: %v, got: %v", i, mean, f.StdDev())
	} else {
		std = f.StdDev()
	}

	// Entropy check.
	for i, x := range xs {
		tmp[i] = -f.LogProb(x)
	}
	entropy := stat.Mean(tmp, nil)
	if !floats.EqualWithinAbsOrRel(entropy, f.Entropy(), tol, tol) {
		t.Errorf("Entropy mismatch case %v: want: %v, got: %v", i, entropy, f.Entropy())
	}

	// Excess Kurtosis check.
	for i, x := range xs {
		tmp[i] = math.Pow(x-mean, 4)
	}
	mu4 := stat.Mean(tmp, nil)
	kurtosis := mu4/(variance*variance) - 3
	if !floats.EqualWithinAbsOrRel(kurtosis, f.ExKurtosis(), tol, tol) {
		t.Errorf("ExKurtosis mismatch case %v: want: %v, got: %v", i, kurtosis, f.ExKurtosis())
	}

	// Skewness check.
	for i, x := range xs {
		tmp[i] = math.Pow(x-mean, 3)
	}
	mu3 := stat.Mean(tmp, nil)
	skewness := mu3 / math.Pow(std, 3)
	if !floats.EqualWithinAbsOrRel(skewness, f.Skewness(), tol, tol) {
		t.Errorf("ExKurtosis mismatch case %v: want: %v, got: %v", i, skewness, f.Skewness())
	}

	// Quantile, CDF, and survival check.
	for i, p := range []float64{0.1, 0.25, 0.5, 0.75, 0.9} {
		x := f.Quantile(p)
		cdf := f.CDF(x)
		estCDF := stat.CDF(x, stat.Empirical, sortedXs, nil)
		if !floats.EqualWithinAbsOrRel(cdf, estCDF, tol, tol) {
			t.Errorf("CDF mismatch case %v: want: %v, got: %v", i, estCDF, cdf)
		}
		if !floats.EqualWithinAbsOrRel(cdf, p, tol, tol) {
			t.Errorf("Quantile/CDF mismatch case %v: want: %v, got: %v", i, p, cdf)
		}
		if math.Abs(1-cdf-f.Survival(x)) > 1e-14 {
			t.Errorf("Survival/CDF mismatch case %v: want: %v, got: %v", i, 1-cdf, f.Survival(x))
		}
	}

	// Prob and LogProb check.
	m := 1001
	bins := make([]float64, m)
	dividers := make([]float64, m)
	floats.Span(bins, 0, 1)
	for i, v := range bins {
		dividers[i] = f.Quantile(v)
	}
	counts := stat.Histogram(nil, dividers, sortedXs, nil)
	// Test PDf against normalized count
	for i, v := range counts {
		v /= float64(n)
		at := f.Quantile((bins[i] + bins[i+1]) / 2)
		prob := f.Prob(at)
		if !floats.EqualWithinAbsOrRel(skewness, f.Skewness(), tol, tol) {
			t.Errorf("Prob mismatch case %v at %v: want: %v, got: %v", i, at, v, prob)
			break
		}
		if math.Abs(math.Log(prob)-f.LogProb(at)) > 1e-14 {
			t.Errorf("Prob and LogProb mismatch case %v at %v: want %v, got %v", i, at, math.Log(prob), f.LogProb(at))
			break
		}
	}
}
Example #7
0
func TestTrapezoidal(t *testing.T) {
	const N = 1e6
	x := floats.Span(make([]float64, N), 0, 1)
	for i, test := range []struct {
		x    []float64
		f    func(x float64) float64
		want float64
	}{
		{
			x:    x,
			f:    func(x float64) float64 { return x },
			want: 0.5,
		},
		{
			x:    floats.Span(make([]float64, N), -1, 1),
			f:    func(x float64) float64 { return x },
			want: 0,
		},
		{
			x:    x,
			f:    func(x float64) float64 { return x + 10 },
			want: 10.5,
		},
		{
			x:    x,
			f:    func(x float64) float64 { return 3*x*x + 10 },
			want: 11,
		},
		{
			x:    x,
			f:    func(x float64) float64 { return math.Exp(x) },
			want: 1.7182818284591876,
		},
		{
			x:    floats.Span(make([]float64, N), 0, math.Pi),
			f:    func(x float64) float64 { return math.Cos(x) },
			want: 0,
		},
		{
			x:    floats.Span(make([]float64, N), 0, 2*math.Pi),
			f:    func(x float64) float64 { return math.Cos(x) },
			want: 0,
		},
		{
			x:    floats.Span(make([]float64, N*10), 0, math.Pi),
			f:    func(x float64) float64 { return math.Sin(x) },
			want: 2,
		},
		{
			x:    floats.Span(make([]float64, N*10), 0, 0.5*math.Pi),
			f:    func(x float64) float64 { return math.Sin(x) },
			want: 1,
		},
		{
			x:    floats.Span(make([]float64, N), 0, 2*math.Pi),
			f:    func(x float64) float64 { return math.Sin(x) },
			want: 0,
		},
	} {
		y := make([]float64, len(test.x))
		for i, v := range test.x {
			y[i] = test.f(v)
		}
		v := Trapezoidal(test.x, y)
		if !floats.EqualWithinAbs(v, test.want, 1e-12) {
			t.Errorf("test #%d: got=%v want=%v\n", i, v, test.want)
		}
	}
}