It compiles
Value: [1e-3 to 4e-1]
This commit is contained in:
		
							parent
							
								
									3a56d6fca4
								
							
						
					
					
						commit
						f2460a5e12
					
				|  | @ -3,6 +3,7 @@ open Expect | ||||||
| open TestHelpers | open TestHelpers | ||||||
| open GenericDist_Fixtures | open GenericDist_Fixtures | ||||||
| 
 | 
 | ||||||
|  | let klDivergence = DistributionOperation.Constructors.logScore_DistEstimateDistAnswer(~env) | ||||||
| // integral from low to high of 1 / (high - low) log(normal(mean, stdev)(x) / (1 / (high - low))) dx | // integral from low to high of 1 / (high - low) log(normal(mean, stdev)(x) / (1 / (high - low))) dx | ||||||
| let klNormalUniform = (mean, stdev, low, high): float => | let klNormalUniform = (mean, stdev, low, high): float => | ||||||
|   -.Js.Math.log((high -. low) /. Js.Math.sqrt(2.0 *. MagicNumbers.Math.pi *. stdev ** 2.0)) +. |   -.Js.Math.log((high -. low) /. Js.Math.sqrt(2.0 *. MagicNumbers.Math.pi *. stdev ** 2.0)) +. | ||||||
|  | @ -11,8 +12,6 @@ let klNormalUniform = (mean, stdev, low, high): float => | ||||||
|   (mean ** 2.0 -. (high +. low) *. mean +. (low ** 2.0 +. high *. low +. high ** 2.0) /. 3.0) |   (mean ** 2.0 -. (high +. low) *. mean +. (low ** 2.0 +. high *. low +. high ** 2.0) /. 3.0) | ||||||
| 
 | 
 | ||||||
| describe("klDivergence: continuous -> continuous -> float", () => { | describe("klDivergence: continuous -> continuous -> float", () => { | ||||||
|   let klDivergence = DistributionOperation.Constructors.klDivergence(~env) |  | ||||||
| 
 |  | ||||||
|   let testUniform = (lowAnswer, highAnswer, lowPrediction, highPrediction) => { |   let testUniform = (lowAnswer, highAnswer, lowPrediction, highPrediction) => { | ||||||
|     test("of two uniforms is equal to the analytic expression", () => { |     test("of two uniforms is equal to the analytic expression", () => { | ||||||
|       let answer = |       let answer = | ||||||
|  | @ -82,7 +81,6 @@ describe("klDivergence: continuous -> continuous -> float", () => { | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| describe("klDivergence: discrete -> discrete -> float", () => { | describe("klDivergence: discrete -> discrete -> float", () => { | ||||||
|   let klDivergence = DistributionOperation.Constructors.klDivergence(~env) |  | ||||||
|   let mixture = a => DistributionTypes.DistributionOperation.Mixture(a) |   let mixture = a => DistributionTypes.DistributionOperation.Mixture(a) | ||||||
|   let a' = [(point1, 1e0), (point2, 1e0)]->mixture->run |   let a' = [(point1, 1e0), (point2, 1e0)]->mixture->run | ||||||
|   let b' = [(point1, 1e0), (point2, 1e0), (point3, 1e0)]->mixture->run |   let b' = [(point1, 1e0), (point2, 1e0), (point3, 1e0)]->mixture->run | ||||||
|  | @ -117,7 +115,6 @@ describe("klDivergence: discrete -> discrete -> float", () => { | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| describe("klDivergence: mixed -> mixed -> float", () => { | describe("klDivergence: mixed -> mixed -> float", () => { | ||||||
|   let klDivergence = DistributionOperation.Constructors.klDivergence(~env) |  | ||||||
|   let mixture' = a => DistributionTypes.DistributionOperation.Mixture(a) |   let mixture' = a => DistributionTypes.DistributionOperation.Mixture(a) | ||||||
|   let mixture = a => { |   let mixture = a => { | ||||||
|     let dist' = a->mixture'->run |     let dist' = a->mixture'->run | ||||||
|  | @ -193,7 +190,7 @@ describe("combineAlongSupportOfSecondArgument0", () => { | ||||||
|     let predictionWrapped = E.R.fmap(a => run(FromDist(ToDist(ToPointSet), a)), prediction) |     let predictionWrapped = E.R.fmap(a => run(FromDist(ToDist(ToPointSet), a)), prediction) | ||||||
| 
 | 
 | ||||||
|     let interpolator = XYShape.XtoY.continuousInterpolator(#Stepwise, #UseZero) |     let interpolator = XYShape.XtoY.continuousInterpolator(#Stepwise, #UseZero) | ||||||
|     let integrand = PointSetDist_Scoring.KLDivergence.integrand |     let integrand = PointSetDist_Scoring.WithDistAnswer.integrand | ||||||
| 
 | 
 | ||||||
|     let result = switch (answerWrapped, predictionWrapped) { |     let result = switch (answerWrapped, predictionWrapped) { | ||||||
|     | (Ok(Dist(PointSet(Continuous(a)))), Ok(Dist(PointSet(Continuous(b))))) => |     | (Ok(Dist(PointSet(Continuous(a)))), Ok(Dist(PointSet(Continuous(b))))) => | ||||||
|  | @ -145,18 +145,9 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => { | ||||||
|         Dist(dist) |         Dist(dist) | ||||||
|       } |       } | ||||||
|     | ToDist(Normalize) => dist->GenericDist.normalize->Dist |     | ToDist(Normalize) => dist->GenericDist.normalize->Dist | ||||||
|     | ToScore(KLDivergence(t2)) => |  | ||||||
|       GenericDist.Score.klDivergence(dist, t2, ~toPointSetFn) |  | ||||||
|       ->E.R2.fmap(r => Float(r)) |  | ||||||
|       ->OutputLocal.fromResult |  | ||||||
|     | ToScore(LogScore(answer, prior)) => |     | ToScore(LogScore(answer, prior)) => | ||||||
|       GenericDist.Score.logScoreWithPointResolution( |       GenericDist.Score.logScore(~estimate=Score_Dist(dist), ~answer, ~prior) | ||||||
|         ~prediction=dist, |       ->E.R2.fmap(s => Float(s)) | ||||||
|         ~answer, |  | ||||||
|         ~prior, |  | ||||||
|         ~toPointSetFn, |  | ||||||
|       ) |  | ||||||
|       ->E.R2.fmap(r => Float(r)) |  | ||||||
|       ->OutputLocal.fromResult |       ->OutputLocal.fromResult | ||||||
|     | ToBool(IsNormalized) => dist->GenericDist.isNormalized->Bool |     | ToBool(IsNormalized) => dist->GenericDist.isNormalized->Bool | ||||||
|     | ToDist(Truncate(leftCutoff, rightCutoff)) => |     | ToDist(Truncate(leftCutoff, rightCutoff)) => | ||||||
|  | @ -271,13 +262,22 @@ module Constructors = { | ||||||
|   let pdf = (~env, dist, f) => C.pdf(dist, f)->run(~env)->toFloatR |   let pdf = (~env, dist, f) => C.pdf(dist, f)->run(~env)->toFloatR | ||||||
|   let normalize = (~env, dist) => C.normalize(dist)->run(~env)->toDistR |   let normalize = (~env, dist) => C.normalize(dist)->run(~env)->toDistR | ||||||
|   let isNormalized = (~env, dist) => C.isNormalized(dist)->run(~env)->toBoolR |   let isNormalized = (~env, dist) => C.isNormalized(dist)->run(~env)->toBoolR | ||||||
|   let klDivergence = (~env, dist1, dist2) => C.klDivergence(dist1, dist2)->run(~env)->toFloatR |   let logScore_DistEstimateDistAnswer = (~env, estimate, answer) => | ||||||
|   let logScoreWithPointResolution = ( |     C.logScore_DistEstimateDistAnswer(estimate, answer)->run(~env)->toFloatR | ||||||
|     ~env, |   let logScore_DistEstimateDistAnswerWithPrior = (~env, estimate, answer, prior) => | ||||||
|     ~prediction: DistributionTypes.genericDist, |     C.logScore_DistEstimateDistAnswerWithPrior(estimate, answer, prior)->run(~env)->toFloatR | ||||||
|     ~answer: float, |   let logScore_DistEstimateScalarAnswer = (~env, estimate, answer) => | ||||||
|     ~prior: option<DistributionTypes.genericDist>, |     C.logScore_DistEstimateScalarAnswer(estimate, answer)->run(~env)->toFloatR | ||||||
|   ) => C.logScoreWithPointResolution(~prediction, ~answer, ~prior)->run(~env)->toFloatR |   let logScore_DistEstimateScalarAnswerWithPrior = (~env, estimate, answer, prior) => | ||||||
|  |     C.logScore_DistEstimateScalarAnswerWithPrior(estimate, answer, prior)->run(~env)->toFloatR | ||||||
|  |   let logScore_ScalarEstimateDistAnswer = (~env, estimate, answer) => | ||||||
|  |     C.logScore_ScalarEstimateDistAnswer(estimate, answer)->run(~env)->toFloatR | ||||||
|  |   let logScore_ScalarEstimateDistAnswerWithPrior = (~env, estimate, answer, prior) => | ||||||
|  |     C.logScore_ScalarEstimateDistAnswerWithPrior(estimate, answer, prior)->run(~env)->toFloatR | ||||||
|  |   let logScore_ScalarEstimateScalarAnswer = (~env, estimate, answer) => | ||||||
|  |     C.logScore_ScalarEstimateScalarAnswer(estimate, answer)->run(~env)->toFloatR | ||||||
|  |   let logScore_ScalarEstimateScalarAnswerWithPrior = (~env, estimate, answer, prior) => | ||||||
|  |     C.logScore_ScalarEstimateScalarAnswerWithPrior(estimate, answer, prior)->run(~env)->toFloatR | ||||||
|   let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR |   let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR | ||||||
|   let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR |   let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR | ||||||
|   let fromSamples = (~env, xs) => C.fromSamples(xs)->run(~env)->toDistR |   let fromSamples = (~env, xs) => C.fromSamples(xs)->run(~env)->toDistR | ||||||
|  |  | ||||||
|  | @ -61,13 +61,40 @@ module Constructors: { | ||||||
|   @genType |   @genType | ||||||
|   let isNormalized: (~env: env, genericDist) => result<bool, error> |   let isNormalized: (~env: env, genericDist) => result<bool, error> | ||||||
|   @genType |   @genType | ||||||
|   let klDivergence: (~env: env, genericDist, genericDist) => result<float, error> |   let logScore_DistEstimateDistAnswer: (~env: env, genericDist, genericDist) => result<float, error> | ||||||
|   @genType |   @genType | ||||||
|   let logScoreWithPointResolution: ( |   let logScore_DistEstimateDistAnswerWithPrior: ( | ||||||
|     ~env: env, |     ~env: env, | ||||||
|     ~prediction: genericDist, |     genericDist, | ||||||
|     ~answer: float, |     genericDist, | ||||||
|     ~prior: option<genericDist>, |     DistributionTypes.DistributionOperation.scoreDistOrScalar, | ||||||
|  |   ) => result<float, error> | ||||||
|  |   @genType | ||||||
|  |   let logScore_DistEstimateScalarAnswer: (~env: env, genericDist, float) => result<float, error> | ||||||
|  |   @genType | ||||||
|  |   let logScore_DistEstimateScalarAnswerWithPrior: ( | ||||||
|  |     ~env: env, | ||||||
|  |     genericDist, | ||||||
|  |     float, | ||||||
|  |     DistributionTypes.DistributionOperation.scoreDistOrScalar, | ||||||
|  |   ) => result<float, error> | ||||||
|  |   @genType | ||||||
|  |   let logScore_ScalarEstimateDistAnswer: (~env: env, float, genericDist) => result<float, error> | ||||||
|  |   @genType | ||||||
|  |   let logScore_ScalarEstimateDistAnswerWithPrior: ( | ||||||
|  |     ~env: env, | ||||||
|  |     float, | ||||||
|  |     genericDist, | ||||||
|  |     DistributionTypes.DistributionOperation.scoreDistOrScalar, | ||||||
|  |   ) => result<float, error> | ||||||
|  |   @genType | ||||||
|  |   let logScore_ScalarEstimateScalarAnswer: (~env: env, float, float) => result<float, error> | ||||||
|  |   @genType | ||||||
|  |   let logScore_ScalarEstimateScalarAnswerWithPrior: ( | ||||||
|  |     ~env: env, | ||||||
|  |     float, | ||||||
|  |     float, | ||||||
|  |     DistributionTypes.DistributionOperation.scoreDistOrScalar, | ||||||
|   ) => result<float, error> |   ) => result<float, error> | ||||||
|   @genType |   @genType | ||||||
|   let toPointSet: (~env: env, genericDist) => result<genericDist, error> |   let toPointSet: (~env: env, genericDist) => result<genericDist, error> | ||||||
|  |  | ||||||
|  | @ -92,7 +92,9 @@ module DistributionOperation = { | ||||||
|     | ToString |     | ToString | ||||||
|     | ToSparkline(int) |     | ToSparkline(int) | ||||||
| 
 | 
 | ||||||
|   type toScore = KLDivergence(genericDist) | LogScore(float, option<genericDist>) |   type scoreDistOrScalar = Score_Dist(genericDist) | Score_Scalar(float) | ||||||
|  | 
 | ||||||
|  |   type toScore = LogScore(scoreDistOrScalar, option<scoreDistOrScalar>) | ||||||
| 
 | 
 | ||||||
|   type fromDist = |   type fromDist = | ||||||
|     | ToFloat(toFloat) |     | ToFloat(toFloat) | ||||||
|  | @ -120,8 +122,7 @@ module DistributionOperation = { | ||||||
|     | ToFloat(#Pdf(r)) => `pdf(${E.Float.toFixed(r)})` |     | ToFloat(#Pdf(r)) => `pdf(${E.Float.toFixed(r)})` | ||||||
|     | ToFloat(#Sample) => `sample` |     | ToFloat(#Sample) => `sample` | ||||||
|     | ToFloat(#IntegralSum) => `integralSum` |     | ToFloat(#IntegralSum) => `integralSum` | ||||||
|     | ToScore(KLDivergence(_)) => `klDivergence` |     | ToScore(_) => `logScore` | ||||||
|     | ToScore(LogScore(x, _)) => `logScore against ${E.Float.toFixed(x)}` |  | ||||||
|     | ToDist(Normalize) => `normalize` |     | ToDist(Normalize) => `normalize` | ||||||
|     | ToDist(ToPointSet) => `toPointSet` |     | ToDist(ToPointSet) => `toPointSet` | ||||||
|     | ToDist(ToSampleSet(r)) => `toSampleSet(${E.I.toString(r)})` |     | ToDist(ToSampleSet(r)) => `toSampleSet(${E.I.toString(r)})` | ||||||
|  | @ -162,10 +163,37 @@ module Constructors = { | ||||||
|     let fromSamples = (xs): t => FromSamples(xs) |     let fromSamples = (xs): t => FromSamples(xs) | ||||||
|     let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist) |     let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist) | ||||||
|     let inspect = (dist): t => FromDist(ToDist(Inspect), dist) |     let inspect = (dist): t => FromDist(ToDist(Inspect), dist) | ||||||
|     let klDivergence = (dist1, dist2): t => FromDist(ToScore(KLDivergence(dist2)), dist1) |     let logScore_DistEstimateDistAnswer = (estimate, answer): t => FromDist( | ||||||
|     let logScoreWithPointResolution = (~prediction, ~answer, ~prior): t => FromDist( |       ToScore(LogScore(Score_Dist(answer), None)), | ||||||
|       ToScore(LogScore(answer, prior)), |       estimate, | ||||||
|       prediction, |     ) | ||||||
|  |     let logScore_DistEstimateDistAnswerWithPrior = (estimate, answer, prior): t => FromDist( | ||||||
|  |       ToScore(LogScore(Score_Dist(answer), Some(prior))), | ||||||
|  |       estimate, | ||||||
|  |     ) | ||||||
|  |     let logScore_DistEstimateScalarAnswer = (estimate, answer): t => FromDist( | ||||||
|  |       ToScore(LogScore(Score_Scalar(answer), None)), | ||||||
|  |       estimate, | ||||||
|  |     ) | ||||||
|  |     let logScore_DistEstimateScalarAnswerWithPrior = (estimate, answer, prior): t => FromDist( | ||||||
|  |       ToScore(LogScore(Score_Scalar(answer), Some(prior))), | ||||||
|  |       estimate, | ||||||
|  |     ) | ||||||
|  |     let logScore_ScalarEstimateDistAnswer = (estimate, answer): t => FromFloat( | ||||||
|  |       ToScore(LogScore(Score_Dist(answer), None)), | ||||||
|  |       estimate, | ||||||
|  |     ) | ||||||
|  |     let logScore_ScalarEstimateDistAnswerWithPrior = (estimate, answer, prior): t => FromFloat( | ||||||
|  |       ToScore(LogScore(Score_Dist(answer), Some(prior))), | ||||||
|  |       estimate, | ||||||
|  |     ) | ||||||
|  |     let logScore_ScalarEstimateScalarAnswer = (estimate, answer): t => FromFloat( | ||||||
|  |       ToScore(LogScore(Score_Scalar(answer), None)), | ||||||
|  |       estimate, | ||||||
|  |     ) | ||||||
|  |     let logScore_ScalarEstimateScalarAnswerWithPrior = (estimate, answer, prior): t => FromFloat( | ||||||
|  |       ToScore(LogScore(Score_Scalar(answer), Some(prior))), | ||||||
|  |       estimate, | ||||||
|     ) |     ) | ||||||
|     let scalePower = (dist, n): t => FromDist(ToDist(Scale(#Power, n)), dist) |     let scalePower = (dist, n): t => FromDist(ToDist(Scale(#Power, n)), dist) | ||||||
|     let scaleLogarithm = (dist, n): t => FromDist(ToDist(Scale(#Logarithm, n)), dist) |     let scaleLogarithm = (dist, n): t => FromDist(ToDist(Scale(#Logarithm, n)), dist) | ||||||
|  |  | ||||||
|  | @ -61,46 +61,6 @@ let integralEndY = (t: t): float => | ||||||
| 
 | 
 | ||||||
| let isNormalized = (t: t): bool => Js.Math.abs_float(integralEndY(t) -. 1.0) < 1e-7 | let isNormalized = (t: t): bool => Js.Math.abs_float(integralEndY(t) -. 1.0) < 1e-7 | ||||||
| 
 | 
 | ||||||
| module Score = { |  | ||||||
|   let klDivergence = (prediction, answer, ~toPointSetFn: toPointSetFn): result<float, error> => { |  | ||||||
|     let pointSets = E.R.merge(toPointSetFn(prediction), toPointSetFn(answer)) |  | ||||||
|     pointSets |> E.R2.bind(((predi, ans)) => |  | ||||||
|       PointSetDist.T.klDivergence(predi, ans)->E.R2.errMap(x => DistributionTypes.OperationError(x)) |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   let logScoreWithPointResolution = ( |  | ||||||
|     ~prediction: DistributionTypes.genericDist, |  | ||||||
|     ~answer: float, |  | ||||||
|     ~prior: option<DistributionTypes.genericDist>, |  | ||||||
|     ~toPointSetFn: toPointSetFn, |  | ||||||
|   ): result<float, error> => { |  | ||||||
|     switch prior { |  | ||||||
|     | Some(prior') => |  | ||||||
|       E.R.merge(toPointSetFn(prior'), toPointSetFn(prediction))->E.R.bind((( |  | ||||||
|         prior'', |  | ||||||
|         prediction'', |  | ||||||
|       )) => |  | ||||||
|         PointSetDist.T.logScoreWithPointResolution( |  | ||||||
|           ~prediction=prediction'', |  | ||||||
|           ~answer, |  | ||||||
|           ~prior=prior''->Some, |  | ||||||
|         )->E.R2.errMap(x => DistributionTypes.OperationError(x)) |  | ||||||
|       ) |  | ||||||
|     | None => |  | ||||||
|       prediction |  | ||||||
|       ->toPointSetFn |  | ||||||
|       ->E.R.bind(x => |  | ||||||
|         PointSetDist.T.logScoreWithPointResolution( |  | ||||||
|           ~prediction=x, |  | ||||||
|           ~answer, |  | ||||||
|           ~prior=None, |  | ||||||
|         )->E.R2.errMap(x => DistributionTypes.OperationError(x)) |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| let toFloatOperation = ( | let toFloatOperation = ( | ||||||
|   t, |   t, | ||||||
|   ~toPointSetFn: toPointSetFn, |   ~toPointSetFn: toPointSetFn, | ||||||
|  | @ -159,6 +119,125 @@ let toPointSet = ( | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | module Score = { | ||||||
|  |   type scoreDistOrScalar = DistributionTypes.DistributionOperation.scoreDistOrScalar | ||||||
|  | 
 | ||||||
|  |   type pointSet_ScoreDistOrScalar = D(PointSetTypes.pointSetDist) | S(float) | ||||||
|  |   let argsMake = ( | ||||||
|  |     ~esti: scoreDistOrScalar, | ||||||
|  |     ~answ: scoreDistOrScalar, | ||||||
|  |     ~prior: option<scoreDistOrScalar>, | ||||||
|  |   ): result<PointSetDist_Scoring.scoreArgs, error> => { | ||||||
|  |     let toPointSetFn = toPointSet( | ||||||
|  |       ~xyPointLength=MagicNumbers.Environment.defaultXYPointLength, | ||||||
|  |       ~sampleCount=MagicNumbers.Environment.defaultSampleCount, | ||||||
|  |       ~xSelection=#ByWeight, | ||||||
|  |     ) | ||||||
|  |     let prior': option<result<pointSet_ScoreDistOrScalar, error>> = switch prior { | ||||||
|  |     | None => None | ||||||
|  |     | Some(Score_Dist(d)) => toPointSetFn(d, ())->E.R.bind(x => x->D->Ok)->Some | ||||||
|  |     | Some(Score_Scalar(s)) => s->S->Ok->Some | ||||||
|  |     } | ||||||
|  |     let twoDists = (esti': t, answ': t): result< | ||||||
|  |       (PointSetTypes.pointSetDist, PointSetTypes.pointSetDist), | ||||||
|  |       error, | ||||||
|  |     > => E.R.merge(toPointSetFn(esti', ()), toPointSetFn(answ', ())) | ||||||
|  |     switch (esti, answ, prior') { | ||||||
|  |     | (Score_Dist(esti'), Score_Dist(answ'), None) => | ||||||
|  |       twoDists(esti', answ')->E.R.bind(((esti'', answ'')) => | ||||||
|  |         {estimate: esti'', answer: answ'', prior: None} | ||||||
|  |         ->PointSetDist_Scoring.DistEstimateDistAnswer | ||||||
|  |         ->Ok | ||||||
|  |       ) | ||||||
|  |     | (Score_Dist(esti'), Score_Dist(answ'), Some(Ok(D(prior'')))) => | ||||||
|  |       twoDists(esti', answ')->E.R.bind(((esti'', answ'')) => | ||||||
|  |         {estimate: esti'', answer: answ'', prior: Some(prior'')} | ||||||
|  |         ->PointSetDist_Scoring.DistEstimateDistAnswer | ||||||
|  |         ->Ok | ||||||
|  |       ) | ||||||
|  |     | (Score_Dist(esti'), Score_Scalar(answ'), None) => | ||||||
|  |       toPointSetFn(esti', ())->E.R.bind(esti'' => | ||||||
|  |         {estimate: esti'', answer: answ', prior: None} | ||||||
|  |         ->PointSetDist_Scoring.DistEstimateScalarAnswer | ||||||
|  |         ->Ok | ||||||
|  |       ) | ||||||
|  |     | (Score_Dist(esti'), Score_Scalar(answ'), Some(Ok(D(prior'')))) => | ||||||
|  |       toPointSetFn(esti', ())->E.R.bind(esti'' => | ||||||
|  |         {estimate: esti'', answer: answ', prior: Some(prior'')} | ||||||
|  |         ->PointSetDist_Scoring.DistEstimateScalarAnswer | ||||||
|  |         ->Ok | ||||||
|  |       ) | ||||||
|  |     | (Score_Scalar(esti'), Score_Dist(answ'), None) => | ||||||
|  |       toPointSetFn(answ', ())->E.R.bind(answ'' => | ||||||
|  |         {estimate: esti', answer: answ'', prior: None} | ||||||
|  |         ->PointSetDist_Scoring.ScalarEstimateDistAnswer | ||||||
|  |         ->Ok | ||||||
|  |       ) | ||||||
|  |     | (Score_Scalar(esti'), Score_Dist(answ'), Some(Ok(S(prior'')))) => | ||||||
|  |       toPointSetFn(answ', ())->E.R.bind(answ'' => | ||||||
|  |         {estimate: esti', answer: answ'', prior: Some(prior'')} | ||||||
|  |         ->PointSetDist_Scoring.ScalarEstimateDistAnswer | ||||||
|  |         ->Ok | ||||||
|  |       ) | ||||||
|  |     | (Score_Scalar(esti'), Score_Scalar(answ'), None) => | ||||||
|  |       {estimate: esti', answer: answ', prior: None} | ||||||
|  |       ->PointSetDist_Scoring.ScalarEstimateScalarAnswer | ||||||
|  |       ->Ok | ||||||
|  |     | (Score_Scalar(esti'), Score_Scalar(answ'), Some(Ok(S(prior'')))) => | ||||||
|  |       {estimate: esti', answer: answ', prior: prior''->Some} | ||||||
|  |       ->PointSetDist_Scoring.ScalarEstimateScalarAnswer | ||||||
|  |       ->Ok | ||||||
|  |     | (_, _, Some(Error(err))) => err->Error | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   let logScore = ( | ||||||
|  |     ~estimate: scoreDistOrScalar, | ||||||
|  |     ~answer: scoreDistOrScalar, | ||||||
|  |     ~prior: option<scoreDistOrScalar>, | ||||||
|  |   ): result<float, error> => | ||||||
|  |     argsMake(~esti=estimate, ~answ=answer, ~prior)->E.R.bind(x => | ||||||
|  |       x->PointSetDist.logScore->E.R2.errMap(y => DistributionTypes.OperationError(y)) | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |   //  let klDivergence = (prediction, answer, ~toPointSetFn: toPointSetFn): result<float, error> => { | ||||||
|  |   //    let pointSets = E.R.merge(toPointSetFn(prediction), toPointSetFn(answer)) | ||||||
|  |   //    pointSets |> E.R2.bind(((predi, ans)) => | ||||||
|  |   //      PointSetDist.T.klDivergence(predi, ans)->E.R2.errMap(x => DistributionTypes.OperationError(x)) | ||||||
|  |   //    ) | ||||||
|  |   //  } | ||||||
|  |   // | ||||||
|  |   //  let logScoreWithPointResolution = ( | ||||||
|  |   //    ~prediction: DistributionTypes.genericDist, | ||||||
|  |   //    ~answer: float, | ||||||
|  |   //    ~prior: option<DistributionTypes.genericDist>, | ||||||
|  |   //    ~toPointSetFn: toPointSetFn, | ||||||
|  |   //  ): result<float, error> => { | ||||||
|  |   //    switch prior { | ||||||
|  |   //    | Some(prior') => | ||||||
|  |   //      E.R.merge(toPointSetFn(prior'), toPointSetFn(prediction))->E.R.bind((( | ||||||
|  |   //        prior'', | ||||||
|  |   //        prediction'', | ||||||
|  |   //      )) => | ||||||
|  |   //        PointSetDist.T.logScoreWithPointResolution( | ||||||
|  |   //          ~prediction=prediction'', | ||||||
|  |   //          ~answer, | ||||||
|  |   //          ~prior=prior''->Some, | ||||||
|  |   //        )->E.R2.errMap(x => DistributionTypes.OperationError(x)) | ||||||
|  |   //      ) | ||||||
|  |   //    | None => | ||||||
|  |   //      prediction | ||||||
|  |   //      ->toPointSetFn | ||||||
|  |   //      ->E.R.bind(x => | ||||||
|  |   //        PointSetDist.T.logScoreWithPointResolution( | ||||||
|  |   //          ~prediction=x, | ||||||
|  |   //          ~answer, | ||||||
|  |   //          ~prior=None, | ||||||
|  |   //        )->E.R2.errMap(x => DistributionTypes.OperationError(x)) | ||||||
|  |   //      ) | ||||||
|  |   //    } | ||||||
|  |   //  } | ||||||
|  | } | ||||||
| /* | /* | ||||||
|   PointSetDist.toSparkline calls "downsampleEquallyOverX", which downsamples it to n=bucketCount. |   PointSetDist.toSparkline calls "downsampleEquallyOverX", which downsamples it to n=bucketCount. | ||||||
|   It first needs a pointSetDist, so we convert to a pointSetDist. In this process we want the  |   It first needs a pointSetDist, so we convert to a pointSetDist. In this process we want the  | ||||||
|  |  | ||||||
|  | @ -25,12 +25,10 @@ let toFloatOperation: ( | ||||||
| ) => result<float, error> | ) => result<float, error> | ||||||
| 
 | 
 | ||||||
| module Score: { | module Score: { | ||||||
|   let klDivergence: (t, t, ~toPointSetFn: toPointSetFn) => result<float, error> |   let logScore: ( | ||||||
|   let logScoreWithPointResolution: ( |     ~estimate: DistributionTypes.DistributionOperation.scoreDistOrScalar, | ||||||
|     ~prediction: t, |     ~answer: DistributionTypes.DistributionOperation.scoreDistOrScalar, | ||||||
|     ~answer: float, |     ~prior: option<DistributionTypes.DistributionOperation.scoreDistOrScalar>, | ||||||
|     ~prior: option<t>, |  | ||||||
|     ~toPointSetFn: toPointSetFn, |  | ||||||
|   ) => result<float, error> |   ) => result<float, error> | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -215,7 +215,7 @@ module T = Dist({ | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| let logScore = (args: PointSetDist_Scoring.scoreArgs): result<float, Operation.Error.t> => | let logScore = (args: PointSetDist_Scoring.scoreArgs): result<float, Operation.Error.t> => | ||||||
|   PointSetDist_Scoring.logScore(args) |   PointSetDist_Scoring.logScore(args, ~combineFn=combinePointwise, ~integrateFn=T.integralEndY) | ||||||
| 
 | 
 | ||||||
| let pdf = (f: float, t: t) => { | let pdf = (f: float, t: t) => { | ||||||
|   let mixedPoint: PointSetTypes.mixedPoint = T.xToY(f, t) |   let mixedPoint: PointSetTypes.mixedPoint = T.xToY(f, t) | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ type t = PointSetTypes.pointSetDist | ||||||
| type continuousShape = PointSetTypes.continuousShape | type continuousShape = PointSetTypes.continuousShape | ||||||
| type discreteShape = PointSetTypes.discreteShape | type discreteShape = PointSetTypes.discreteShape | ||||||
| type mixedShape = PointSetTypes.mixedShape | type mixedShape = PointSetTypes.mixedShape | ||||||
|  | 
 | ||||||
| type scalar = float | type scalar = float | ||||||
| type abstractScoreArgs<'a, 'b> = {estimate: 'a, answer: 'b, prior: option<'a>} | type abstractScoreArgs<'a, 'b> = {estimate: 'a, answer: 'b, prior: option<'a>} | ||||||
| type scoreArgs = | type scoreArgs = | ||||||
|  | @ -9,6 +10,7 @@ type scoreArgs = | ||||||
|   | DistEstimateScalarAnswer(abstractScoreArgs<t, scalar>) |   | DistEstimateScalarAnswer(abstractScoreArgs<t, scalar>) | ||||||
|   | ScalarEstimateDistAnswer(abstractScoreArgs<scalar, t>) |   | ScalarEstimateDistAnswer(abstractScoreArgs<scalar, t>) | ||||||
|   | ScalarEstimateScalarAnswer(abstractScoreArgs<scalar, scalar>) |   | ScalarEstimateScalarAnswer(abstractScoreArgs<scalar, scalar>) | ||||||
|  | 
 | ||||||
| let logFn = Js.Math.log // base e | let logFn = Js.Math.log // base e | ||||||
| let minusScaledLogOfQuot = (~esti, ~answ): result<float, Operation.Error.t> => { | let minusScaledLogOfQuot = (~esti, ~answ): result<float, Operation.Error.t> => { | ||||||
|   let quot = esti /. answ |   let quot = esti /. answ | ||||||
|  | @ -56,7 +58,7 @@ module WithScalarAnswer = { | ||||||
|   } |   } | ||||||
|   let scoreWithPrior' = ( |   let scoreWithPrior' = ( | ||||||
|     ~estimatePdf: float => float, |     ~estimatePdf: float => float, | ||||||
|     ~answer: float, |     ~answer: scalar, | ||||||
|     ~priorPdf: float => float, |     ~priorPdf: float => float, | ||||||
|   ): result<float, Operation.Error.t> => { |   ): result<float, Operation.Error.t> => { | ||||||
|     let numerator = answer->estimatePdf |     let numerator = answer->estimatePdf | ||||||
|  | @ -69,23 +71,44 @@ module WithScalarAnswer = { | ||||||
|       minusScaledLogOfQuot(~esti=numerator, ~answ=priorDensityOfAnswer) |       minusScaledLogOfQuot(~esti=numerator, ~answ=priorDensityOfAnswer) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   let score = (~estimate: t, ~answer: t, ~mapper): result<float, Operation.Error.t> => { |   let score = (~estimate: t, ~answer: scalar): result<float, Operation.Error.t> => { | ||||||
|     let pdf = (shape, ~x) => XYShape.XtoY.linear(x, shape.xyShape) |     let estimatePdf = x => | ||||||
|     let estimatePdf = mapper((x => pdf(~x), x => pdf(~x), x => pdf(~x))) |       switch estimate { | ||||||
|  |       | Continuous(esti) => XYShape.XtoY.linear(x, esti.xyShape) | ||||||
|  |       | Discrete(esti) => XYShape.XtoY.linear(x, esti.xyShape) | ||||||
|  |       | Mixed(esti) => | ||||||
|  |         XYShape.XtoY.linear(x, esti.continuous.xyShape) +. | ||||||
|  |         XYShape.XtoY.linear(x, esti.discrete.xyShape) | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|     score'(~estimatePdf, ~answer) |     score'(~estimatePdf, ~answer) | ||||||
|   } |   } | ||||||
|   let scoreWithPrior = (~estimate: t, ~answer: t, ~prior: t, ~mapper): result< |   let scoreWithPrior = (~estimate: t, ~answer: scalar, ~prior: t): result< | ||||||
|     float, |     float, | ||||||
|     Operation.Error.t, |     Operation.Error.t, | ||||||
|   > => { |   > => { | ||||||
|     let estimatePdf = x => XYShape.XtoY.linear(x, estimate.xyShape) |     let estimatePdf = x => | ||||||
|     let priorPdf = x => XYShape.XtoY.linear(x, prior.xyShape) |       switch estimate { | ||||||
|  |       | Continuous(esti) => XYShape.XtoY.linear(x, esti.xyShape) | ||||||
|  |       | Discrete(esti) => XYShape.XtoY.linear(x, esti.xyShape) | ||||||
|  |       | Mixed(esti) => | ||||||
|  |         XYShape.XtoY.linear(x, esti.continuous.xyShape) +. | ||||||
|  |         XYShape.XtoY.linear(x, esti.discrete.xyShape) | ||||||
|  |       } | ||||||
|  |     let priorPdf = x => | ||||||
|  |       switch prior { | ||||||
|  |       | Continuous(prio) => XYShape.XtoY.linear(x, prio.xyShape) | ||||||
|  |       | Discrete(prio) => XYShape.XtoY.linear(x, prio.xyShape) | ||||||
|  |       | Mixed(prio) => | ||||||
|  |         XYShape.XtoY.linear(x, prio.continuous.xyShape) +. | ||||||
|  |         XYShape.XtoY.linear(x, prio.discrete.xyShape) | ||||||
|  |       } | ||||||
|     scoreWithPrior'(~estimatePdf, ~answer, ~priorPdf) |     scoreWithPrior'(~estimatePdf, ~answer, ~priorPdf) | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module TwoScalars = { | module TwoScalars = { | ||||||
|   let score = (~estimate: float, ~answer: float) => |   let score = (~estimate: scalar, ~answer: scalar) => | ||||||
|     if answer == 0.0 { |     if answer == 0.0 { | ||||||
|       0.0->Ok |       0.0->Ok | ||||||
|     } else if estimate == 0.0 { |     } else if estimate == 0.0 { | ||||||
|  | @ -107,9 +130,9 @@ module TwoScalars = { | ||||||
| let logScore = (args: scoreArgs, ~combineFn, ~integrateFn): result<float, Operation.Error.t> => | let logScore = (args: scoreArgs, ~combineFn, ~integrateFn): result<float, Operation.Error.t> => | ||||||
|   switch args { |   switch args { | ||||||
|   | DistEstimateDistAnswer({estimate, answer, prior: None}) => |   | DistEstimateDistAnswer({estimate, answer, prior: None}) => | ||||||
|     WithDistAnswer.sum(~estimate, ~answer, ~integrateFn) |     WithDistAnswer.sum(~estimate, ~answer, ~integrateFn, ~combineFn) | ||||||
|   | DistEstimateDistAnswer({estimate, answer, prior: Some(prior)}) => |   | DistEstimateDistAnswer({estimate, answer, prior: Some(prior)}) => | ||||||
|     WithDistAnswer.sumWithPrior(~estimate, ~answer, ~prior, ~integrateFn) |     WithDistAnswer.sumWithPrior(~estimate, ~answer, ~prior, ~integrateFn, ~combineFn) | ||||||
|   | DistEstimateScalarAnswer({estimate, answer, prior: None}) => |   | DistEstimateScalarAnswer({estimate, answer, prior: None}) => | ||||||
|     WithScalarAnswer.score(~estimate, ~answer) |     WithScalarAnswer.score(~estimate, ~answer) | ||||||
|   | DistEstimateScalarAnswer({estimate, answer, prior: Some(prior)}) => |   | DistEstimateScalarAnswer({estimate, answer, prior: Some(prior)}) => | ||||||
|  |  | ||||||
|  | @ -162,20 +162,6 @@ module Helpers = { | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   let klDivergenceWithPrior = ( |  | ||||||
|     prediction: DistributionTypes.genericDist, |  | ||||||
|     answer: DistributionTypes.genericDist, |  | ||||||
|     prior: DistributionTypes.genericDist, |  | ||||||
|     env: DistributionOperation.env, |  | ||||||
|   ) => { |  | ||||||
|     let term1 = DistributionOperation.Constructors.klDivergence(~env, prediction, answer) |  | ||||||
|     let term2 = DistributionOperation.Constructors.klDivergence(~env, prior, answer) |  | ||||||
|     switch E.R.merge(term1, term2)->E.R2.fmap(((a, b)) => a -. b) { |  | ||||||
|     | Ok(x) => x->DistributionOperation.Float->Some |  | ||||||
|     | Error(_) => None |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module SymbolicConstructors = { | module SymbolicConstructors = { | ||||||
|  | @ -226,28 +212,20 @@ let dispatchToGenericOutput = ( | ||||||
|       ~env, |       ~env, | ||||||
|     )->Some |     )->Some | ||||||
|   | ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env) |   | ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env) | ||||||
|   | ("klDivergence", [EvDistribution(prediction), EvDistribution(answer)]) => |   | ("klDivergence", [EvDistribution(estimate), EvDistribution(answer)]) => | ||||||
|     Some(DistributionOperation.run(FromDist(ToScore(KLDivergence(answer)), prediction), ~env)) |     Some( | ||||||
|   | ("klDivergence", [EvDistribution(prediction), EvDistribution(answer), EvDistribution(prior)]) => |  | ||||||
|     Helpers.klDivergenceWithPrior(prediction, answer, prior, env) |  | ||||||
|   | ( |  | ||||||
|     "logScoreWithPointAnswer", |  | ||||||
|     [EvDistribution(prediction), EvNumber(answer), EvDistribution(prior)], |  | ||||||
|   ) |  | ||||||
|   | ( |  | ||||||
|     "logScoreWithPointAnswer", |  | ||||||
|     [EvDistribution(prediction), EvDistribution(Symbolic(#Float(answer))), EvDistribution(prior)], |  | ||||||
|   ) => |  | ||||||
|       DistributionOperation.run( |       DistributionOperation.run( | ||||||
|       FromDist(ToScore(LogScore(answer, prior->Some)), prediction), |         FromDist(ToScore(LogScore(Score_Dist(answer), None)), estimate), | ||||||
|         ~env, |         ~env, | ||||||
|     )->Some |       ), | ||||||
|   | ("logScoreWithPointAnswer", [EvDistribution(prediction), EvNumber(answer)]) |     ) | ||||||
|   | ( |   | ("klDivergence", [EvDistribution(estimate), EvDistribution(answer), EvDistribution(prior)]) => | ||||||
|     "logScoreWithPointAnswer", |     Some( | ||||||
|     [EvDistribution(prediction), EvDistribution(Symbolic(#Float(answer)))], |       DistributionOperation.run( | ||||||
|   ) => |         FromDist(ToScore(LogScore(Score_Dist(answer), Some(Score_Dist(prior)))), estimate), | ||||||
|     DistributionOperation.run(FromDist(ToScore(LogScore(answer, None)), prediction), ~env)->Some |         ~env, | ||||||
|  |       ), | ||||||
|  |     ) | ||||||
|   | ("isNormalized", [EvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env) |   | ("isNormalized", [EvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env) | ||||||
|   | ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env) |   | ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env) | ||||||
|   | ("scaleLog", [EvDistribution(dist)]) => |   | ("scaleLog", [EvDistribution(dist)]) => | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user