Пример #1
0
    def test_fit_pwl_unimodal_with_forced_direction(self):
        x = np.arange(51, dtype=float) / 10
        y = pwlcurve.PWLCurve([(0, 0), (1, 2), (2, 5), (3, 2), (4, 0)]).eval(x)

        # y is concave down, so a concave solution is ideal.
        concave_curve = fitter.fit_pwl(
            x,
            y,
            num_segments=4,
            fx=transform.identity,
            mono=fitter.MonoType.bitonic_concave_down)
        convex_curve = fitter.fit_pwl(x,
                                      y,
                                      num_segments=4,
                                      fx=transform.identity,
                                      mono=fitter.MonoType.bitonic_concave_up)

        self.assert_allclose(y, concave_curve.eval(x))
        self.assert_notallclose(y, convex_curve.eval(x))

        # -y is concave up, so a convex solution is ideal.
        concave_curve = fitter.fit_pwl(
            x,
            -y,
            num_segments=4,
            fx=transform.identity,
            mono=fitter.MonoType.bitonic_concave_down)
        convex_curve = fitter.fit_pwl(x,
                                      -y,
                                      num_segments=4,
                                      fx=transform.identity,
                                      mono=fitter.MonoType.bitonic_concave_up)

        self.assert_allclose(-y, convex_curve.eval(x))
        self.assert_notallclose(-y, concave_curve.eval(x))
Пример #2
0
    def test_learn_ends_has_no_effect_when_endpoints_are_ideal(self):
        # In this case, the ideal fit uses the endpoints, so no need to learn ends.
        x = np.arange(51, dtype=float)
        y = pwlcurve.PWLCurve([(0, 0), (10, 1), (25, 25), (50, 60)]).eval(x)
        w = np.ones_like(x)

        self.assertEqual(fitter.fit_pwl(x, y, w, 3, learn_ends=True),
                         fitter.fit_pwl(x, y, w, 3, learn_ends=False))
Пример #3
0
 def test_one_segment_pwl_with_flat_ends(self):
     x = np.arange(51, dtype=float)
     y = pwlcurve.PWLCurve([(0, 0), (10, 0), (40, 50), (50, 50)]).eval(x)
     w = np.ones_like(x)
     # A one-segment PWLCurve can fit fn perfectly, but only if its knots are
     # [(10, 0), (40, 50)]. This test confirms that fit_pwl learns those knots.
     curve = fitter.fit_pwl(x, y, w, 1)
     self.assert_allclose([(10, 0), (40, 50)], curve.points)
     self.assert_allclose(y, curve.eval(x))
     self.assertEqual(transform.identity, curve.fx)
Пример #4
0
 def test_non_mono_increasing_two_segment_pwl_with_flat_ends(self):
   x = np.arange(51, dtype=float)
   y = pwlcurve.PWLCurve([(0, 0), (10, 0), (25, 15), (40, 0), (50, 0)]).eval(x)
   w = np.ones_like(x)
   # A two-segment PWLCurve can fit fn perfectly, but only if its knots are
   # [(10, 0), (25, 15), (40, 0)]. This test confirms that fit_pwl will learn
   # those knots.
   curve = fitter.fit_pwl(x, y, w, 2, mono=False, fx=transform.identity)
   self.assert_allclose([(10, 0), (25, 15), (40, 0)], curve.points)
   self.assert_allclose(y, curve.eval(x))
Пример #5
0
 def test_one_segment_pwl_with_flat_ends_but_no_learning_ends(self):
     x = np.arange(51, dtype=float)
     y = pwlcurve.PWLCurve([(0, 0), (10, 0), (40, 50), (50, 50)]).eval(x)
     w = np.ones_like(x)
     # A one-segment PWLCurve can fit fn perfectly, but only if its knots are
     # [(10, 0), (40, 50)]. In this test, we disable learn_ends, and show that
     # the fitter can't learn the ideal fit because it's forced to use 0 and 50
     # as control points.
     curve = fitter.fit_pwl(x, y, w, 1, learn_ends=False)
     self.assertEqual([0, 50], curve.xs)
     self.assert_notallclose(y, curve.eval(x))
Пример #6
0
  def test_fit_pwl_unimodal_on_non_unimodal_data(self):
    x = np.arange(51, dtype=float) / 10
    y = pwlcurve.PWLCurve([(0, 0), (1, 2), (2, 0), (3, 2), (4, 0)]).eval(x)

    curve = fitter.fit_pwl(x, y, num_segments=4, fx=transform.identity,
                           mono=fitter.MonoType.bitonic)

    # An unrestricted fit should change directions three times, but a unimodal
    # curve will only change once.
    self.assertEqual(1, count_slope_inversions(curve.ys))

    # Should be concave down -- increasing at first, decreasing at the end.
    self.assertLess(curve.ys[0], curve.ys[1])
    self.assertLess(curve.ys[-1], curve.ys[-2])
Пример #7
0
  def test_mono_type_enum_and_bool(self):
    np.random.seed(48440)
    x = np.sort(np.random.uniform(size=100))
    y = np.random.normal(size=100)
    w = np.random.uniform(size=100)
    # fit_pwl treats mono=True as synonymous to mono=MonoType.mono.
    self.assertEqual(fitter.fit_pwl(x, y, w, 2, mono=True),
                     fitter.fit_pwl(x, y, w, 2, mono=fitter.MonoType.mono))
    self.assertNotEqual(
        fitter.fit_pwl(x, y, w, 2, mono=True),
        fitter.fit_pwl(x, y, w, 2, mono=fitter.MonoType.nonmono))

    # fit_pwl treats mono=False as synonymous to mono=MonoType.nonmono.
    self.assertEqual(fitter.fit_pwl(x, y, w, 2, mono=False),
                     fitter.fit_pwl(x, y, w, 2, mono=fitter.MonoType.nonmono))
    self.assertNotEqual(fitter.fit_pwl(x, y, w, 2, mono=False),
                        fitter.fit_pwl(x, y, w, 2, mono=fitter.MonoType.mono))
Пример #8
0
def pwl_predict(x, y, *args, **kwargs):
    """Test utility to fit and evaluate a curve in one function."""
    return fitter.fit_pwl(x, y, *args, **kwargs).eval(x)