Skip to content

Instantly share code, notes, and snippets.

@gvergnaud
Last active April 16, 2016 11:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gvergnaud/7c2e340add933727594f71deb1ab3df5 to your computer and use it in GitHub Desktop.
Save gvergnaud/7c2e340add933727594f71deb1ab3df5 to your computer and use it in GitHub Desktop.
/* ----------------------------------------- *
Learning Machin Learning
* ----------------------------------------- */
import { compose, map, chain, range } from 'ramda'
// Result = { a :: Int, b :: Int, cost :: Number }
// Data = [Int, Int]
// Tupple = [Int, Int]
// findBestResult :: [Result] -> Result
const findBestResult = (results) =>
results.reduce(
(bestResult, result) => result.cost < bestResult.cost ? result : bestResult,
{ cost: Infinity }
)
// getSquareError :: Tupple -> Data -> Int
const getSquareError = ([a, b]) => ([x, y]) =>
((a + b * x) - y) ** 2
// sum :: List a -> (a -> Int) -> Int
const sum = (list, transformer) =>
list.reduce((acc, item) => acc + transformer(item), 0)
// getResult :: List Data -> Tupple -> Result
const getResult = dataSet => ([a, b]) => ({
a,
b,
cost: sum(dataSet, getSquareError([a, b])) / (2 * dataSet.length)
})
// resultToTupple :: Result a b -> Tupple a b
const resultToTupple = ({ a, b }) => [a, b]
const log = x => {
console.log(x)
return x
}
// List Data -> List Tupple -> Result
const getBestTupple = dataSet => compose(
resultToTupple,
log,
findBestResult,
map(getResult(dataSet))
)
// granularRange :: Number a -> Number b -> Number -> List [0..a, 0..b]
const granularRange = (start, end, granularity) =>
map(x => x / granularity, range(start * granularity, end * granularity))
// createTuppleRange List a -> List b -> List [a, b]
const createTuppleRange = (as, bs) =>
chain(a => map(b => [a, b], bs), as)
// linearRegression :: List Data -> List Tupple -> (a -> Int) -> Int
export default function linearRegression(dataSet) {
const getBestTuppleForDataSet = (a, b, changeA) => {
const [bestA, bestB] = getBestTupple(dataSet)(
createTuppleRange(
granularRange(a.start, a.end, a.granularity),
granularRange(b.start, b.end, b.granularity)
)
)
if (a.granularity >= 100) return [bestA, bestB]
return getBestTuppleForDataSet(
changeA
? { start: bestA - 1 / a.granularity, end: bestA + 1 / a.granularity, granularity: a.granularity * 10 }
: a,
{ start: bestB - 1 / b.granularity, end: bestB + 1 / b.granularity, granularity: b.granularity * 10 },
b.granularity >= 1
)
}
const [a, b] = getBestTuppleForDataSet(
{ start: -1000, end: 1000, granularity: .01 },
{ start: -1000, end: 1000, granularity: .01 }
)
return x => a + b * x
}
/* ----------------------------------------- *
Usage
* ----------------------------------------- */
const trainingSet = [
{
size: 2104,
price: 460
},
{
size: 1416,
price: 232
},
{
size: 1534,
price: 315
},
{
size: 852,
price: 178
},
{
size: 852,
price: 178
},
{
size: 2500,
price: 500
},
{
size: 2320,
price: 423
}
]
const cleanData = map(({ size, price }) => [size, price])
const h = linearRegression(cleanData(trainingSet))
console.log(`size: ${1503}, estimated price ${h(1503)}`)
console.log(`size: ${2000}, estimated price ${h(2000)}`)
console.log(`size: ${1000}, estimated price ${h(1000)}`)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment