Last active
April 13, 2022 20:47
-
-
Save Phryxia/0bfb659a7a3a34d5c08110fdd848d53f to your computer and use it in GitHub Desktop.
Find simple binary decision boundary of heaviside step function using binary search
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export interface FinderOption { | |
| f: (x: number) => boolean | |
| p: number | |
| epsilon: number | |
| } | |
| // This is theoretically pure, but impractical since this may result stack overflow due to heavy recursion | |
| export function findDecisionBoundary(option: FinderOption, lower: number, upper: number, n: number = 0): { | |
| boundary?: number | |
| n: number | |
| } { | |
| const { f, p, epsilon } = option | |
| const m = lower * p + upper * (1 - p) | |
| const fm = f(m) | |
| if (upper - lower <= epsilon) { | |
| if (fm) return { boundary: m, n } | |
| return { n } | |
| } | |
| if (fm) return findDecisionBoundary(option, lower, m + epsilon * p / 2, n + 1) | |
| return findDecisionBoundary(option, m, upper, n + 1) | |
| } | |
| export function findDecisionBoundaryIterative({ f, p, epsilon }: FinderOption, lower: number, upper: number): { | |
| boundary?: number | |
| n: number | |
| } { | |
| let n = 0 | |
| let prev = 1e+10 | |
| do { | |
| const m = lower * p + upper * (1 - p) | |
| const fm = f(m) | |
| const diff = upper - lower | |
| // convergence detection | |
| if (diff <= epsilon || prev === diff) { | |
| if (fm) return { boundary: m, n } | |
| return { n } | |
| } | |
| prev = diff | |
| if (fm) { | |
| upper = m + epsilon * p / 2 | |
| } else { | |
| lower = m | |
| } | |
| n += 1 | |
| } while (n <= 1024) // prevent infinite loop | |
| return { boundary: lower * p + upper * (1 - p), n } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is an algorithm searching for one dimensional simple binary decision boundary.
Let f be the function between R and
{0, 1}wheref(x) = x >= B ? 1 : 0.Here B is unknown so that we want to find it efficiently.
Our computer has limitation of discretization, so it'll try to find an open set (L, U) includes B and approximates B using linear interpolation of L and U. Here the objective U - L ≤ ε.
By using above algorithm with L = inf(dom(f)) and U = sup(dom(f)), I observed that empirical average complexity goes O(-lg ε) with respect to precision ε.
Maybe it is due to similarity between this and classical binary search.
Note that p / 2 in the
upper = m + epsilon * p / 2must be preserved. This guarantees that algorithm never fall into infinite loop.Theoretically any positive non zero number below p is ok. (explanation in Korean. I'm still working in progress)
Now the optimal p is 0.5 which is pretty intuitive, but I can't prove this as I'm not an expert computer scientist. But by conducting a simple experiment, I observed that p = 0.5 makes the lowest iterations in average. Roughly speaking, using binary search dividing not equally has fairly bad edge case (which the wanted value is placed on the opposite side), and same thing works with real numbers.