Vectorized Evaluation¶
vectorized
¶
Evaluate a distribution over many points at once.
This module is a thin shim now. It exists because it was public in 0.4.0, and everything in it forwards to the distribution methods, which take an array directly since 0.5.0::
>>> from heavytails import Pareto
>>> from heavytails.vectorized import cdf
>>> values = cdf(Pareto(alpha=2.0, xm=1.0), [1.0, 2.0, 10.0])
>>> [round(float(v), 4) for v in values]
[0.0, 0.75, 0.99]
Pareto(alpha=2.0, xm=1.0).cdf([1.0, 2.0, 10.0]) is the same call and is
what new code should write.
What used to be here, and why it is not. This module held a hand-written NumPy kernel for each of 32 (family, method) pairs, each one a transcription of the scalar method with the same name, including its guards. The scalar methods were the reference implementation and the kernels were the fast path, and the test suite compared the two element by element because a transcription can drop a guard, mirror a branch the wrong way, or use a mathematically equal form that rounds differently.
That arrangement cost more than it looks. The tolerance holding the two paths
together had to be rewritten twice before it was right -- once after asserting
bit-identity that held on Windows and failed on every Linux job, and again
after a relative budget that a single unit in the last place of pow could
exceed by four thousand. Neither was a bug in the formulas; both were the price
of having two of them.
The same shape has since turned up twice more in this library. streaming.py
carried a transcription of the Hill estimator described as matching it
"operation for operation", which broke the moment the original changed its
summation. And a metadata test held a third copy of the citation title, so it
could not notice that the two files it compared had both moved. A transcription
cannot tell that it has gone stale.
So there is one implementation now. The formula lives in the method, the method takes an array, and this module forwards to it.
accelerated
¶
Report whether this call evaluates as a single NumPy expression.
Worth checking before assuming a speedup: LogNormal, StudentT, InverseGamma and BetaPrime compute their probabilities one element at a time, because NumPy has neither the error function nor the incomplete beta and gamma.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist
|
Any
|
A distribution instance. |
required |
method
|
str
|
One of |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the call is a single NumPy expression, False if it loops. |
Note
This answers for the distributions in this library. A distribution defined elsewhere, whose methods take only scalars, is reported as accelerated, because there is no way to ask a method how it is written. Before 0.5.0 the answer came from a table of the families this module knew about, so an unknown class was reported as not accelerated.
Examples:
>>> from heavytails import LogNormal, Pareto
>>> accelerated(Pareto(alpha=2.0, xm=1.0), "cdf")
True
>>> accelerated(LogNormal(mu=0.0, sigma=1.0), "cdf")
False
>>> accelerated(LogNormal(mu=0.0, sigma=1.0), "pdf")
True
>>> accelerated(Pareto(alpha=2.0, xm=1.0), "nonsense")
False
Source code in heavytails/vectorized.py
cdf
¶
Distribution function at every point in values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist
|
Any
|
A distribution instance. |
required |
values
|
Sequence[float]
|
Points to evaluate at. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
An array of probabilities, in the order given. |
Examples:
>>> from heavytails import Pareto
>>> [round(float(v), 4) for v in cdf(Pareto(alpha=2.0, xm=1.0), [2.0, 10.0])]
[0.75, 0.99]
Source code in heavytails/vectorized.py
pdf
¶
Density at every point in values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist
|
Any
|
A distribution instance. |
required |
values
|
Sequence[float]
|
Points to evaluate at. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
An array of densities, in the order given. |
Examples:
>>> from heavytails import Pareto
>>> [round(float(v), 4) for v in pdf(Pareto(alpha=2.0, xm=1.0), [1.0, 2.0])]
[2.0, 0.25]
Source code in heavytails/vectorized.py
ppf
¶
Quantile at every probability in probabilities.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist
|
Any
|
A distribution instance. |
required |
probabilities
|
Sequence[float]
|
Probabilities in (0, 1). |
required |
Returns:
| Type | Description |
|---|---|
Any
|
An array of quantiles, in the order given. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If any probability is outside (0, 1). |
Examples:
>>> from heavytails import Pareto
>>> [round(float(v), 4) for v in ppf(Pareto(alpha=2.0, xm=1.0), [0.5, 0.99])]
[1.4142, 10.0]
Source code in heavytails/vectorized.py
sf
¶
Survival function at every point in values.
Computed directly rather than as 1 - cdf, which is what keeps it
accurate far into the tail. See the distribution methods themselves.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist
|
Any
|
A distribution instance. |
required |
values
|
Sequence[float]
|
Points to evaluate at. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
An array of survival probabilities, in the order given. |
Examples:
>>> from heavytails import Pareto
>>> [round(float(v), 4) for v in sf(Pareto(alpha=2.0, xm=1.0), [2.0, 10.0])]
[0.25, 0.01]