JavaScript 也能做机器学习(1)

每当谈起机器学习、深度学习,大家自然就会想到 python c++ GPU tensorflow python 这些词。似乎距离前端人员比较遥远的事 ,今天我们就用 js 来实现一个简单分类的算法。

一切从简单开始,从一个分类问题开始吧。任务就是一个二分类的问题,通过既有的数据训练得到一个模型,然后用模型来对一个数据预测其属于哪一个类别,来了解是如何使用 javascript 进行机器学习。

const R = require('ramda');
randomPoints = R.range(0,5);

这里引入了 ramda 库帮助生成随机数,实现起来很简单。

[ 0, 1, 2, 3, 4 ] 
var rand = (high,low)=> Math.random()*(high - low) + low
randomPoints = R.range(0,100).map(_=> rand(-1,1));

生成在 -1 到 1 之间的随机数,这里使用 map 方法来实现返回在某个区间的随机数、

[ -0.9515869798311445,
  -0.884506721474116,
  0.7849131001955243,
  -0.8271371680230728,
  0.6015755023017424,

上面随机数,然后我们用这些随机数生成随机点,x 和 y 都是 -1 到 1 之间随机数

randomPoints = R.range(0,100).map(_=> (
    {
        x:rand(-1,1),
        y:rand(-1,1)
    }));

我们将这些随机点通过 svg 以绘制在宽和高同为 400 的区域来显示,让你更直观地观察机器学习的过程。

// const R = require('ramda');

var rand = (high,low)=> Math.random()*(high - low) + low

const X_MAX = 400;
const Y_MAX = 400;

randomPoints = R.range(0,100).map(_=> (
    {
        x:rand(0,X_MAX),
        y:rand(0,Y_MAX)
    }));

    console.log(randomPoints)

var html=`
    <svg width="${X_MAX}" height="${Y_MAX}">
        ${randomPoints.map(point=>
            `<circle 
                cx="${point.x}"
                cy="${point.y}"
                r="5"
                />`
        )}
        <line x1="0" x2="${X_MAX}" y1="0" y2="${Y_MAX}" stroke="purple"/>
    </svg>
`;

document.getElementById("app").innerHTML = html;

并且将这些随机点显示出来,这些点散落在宽高都是 400 的个方形区域,然后绘制一条线,这条线就是我们随后拟合分割线,这条线将这些样本点分成了两个类别,位于线上部分是一个类别,位于线下面又是一个类别。

其实问题很简单,只要某一个点 y 坐标大于 x 坐标,或者 y 坐标小于 x 坐标属于另一个类别,如果某一个点 x 坐标大于 y 输入 1 否则 -1 也就是用 1 和 -1 表示两个类别

var team = point => point.x > point.y ? 1 : -1;

接下来通过颜色来表示两个不同类别,类别为 -1 的点用蓝色来表示,而 1 则用红色点来表示。

var html=`
    <svg width="${X_MAX}" height="${Y_MAX}">
        ${randomPoints.map(point=>
            `<circle 
                cx="${point.x}"
                cy="${point.y}"
                r="5"
                fill="${team(point)===-1?'blue':'red'}"
                />`
        )}
        <line x1="0" x2="${X_MAX}" y1="0" y2="${Y_MAX}" stroke="purple"/>
    </svg>
`;

team 函数通过简单逻辑(规则)对随机点进行分类,通过点的 x 和 y 值大小进行判断可以进行判断。

开始写模型

好接下来我们就开始构建 AI 来模拟机器学习过程。初始一个随机参数模型参数比较有意思是两个取值从 -1 到 1 的随机数,这里这样理解我们通过 x 和 y 之间比值来划分 ax + by

a x + b y = 0

var randomWeights = ({
    x:rand(-1,1),
    y:rand(-1,1)
})

这里 guess 函数会输出一个类别,也就是我们函数模型,这里有连个参数,或者叫做权重,权重负责根据 x 和 y 给出一个该点所属类别 1 * x + -1*y > 0 这个关系。

var guess =(weights,point) => {
    const sum = 
        point.x * weights.x +
        point.y * weights.y
    const team = sum >= 0 ? 1 : -1
    return team
}

testGuess = guess(randomWeights,{x:300,y:400})

这里 weights 是权重,point 是输入,sum 为输入和权重乘积的和,这个神经元有两个输入 x 和 y(两个特征)然后输出为 1 或 -1

var html=`
    <svg width="${X_MAX}" height="${Y_MAX}">
        ${randomPoints.map(point=>
            `<circle 
                cx="${point.x}"
                cy="${point.y}"
                r="5"
                fill="${guess(randomWeights,point)===-1?'blue':'red'}"
                />`
        )}
        <line x1="0" x2="${X_MAX}" y1="0" y2="${Y_MAX}" stroke="purple"/>
    </svg>
`;

以为 weight 是随机数,我们每次刷新会得到不同结果。

创建我们训练函数,训练接收 weights 和 point 输入,以及期望值 actualTeam 通过对比判断结果和期望值对比来反馈到训练,进行优化调整weight 获取正确计算模型

function train(weights,point, actualTeam){
    //loss

    //otimizer
}
function train(weights,point, actualTeam){
    //loss
    const guessResult = guess(weights,point) //1
    const error = actualTeam - guessResult;
    return error
    //otimizer
}
var testTrain = () => {
    const point = {x:200,y:400}
    return train(randomWeights,point,team(point))
}
console.log(`result ${testTrain()}`)

上面代码可以简单测试我们计算结果和实际期望值的差距。

function train(weights,point, actualTeam){
    //loss
    const guessResult = guess(weights,point) //1
    const error = actualTeam - guessResult;
    return {
        x: weights.x + (point.x * error),
        y: weights.y + (point.y * error)
    }
    //otimizer
}

在 trainedWeights 方法中,通过给定点来训练出权重,我们通过返回训练 weights 做为下一次参数传入到 train 不断调整 weight。

var trainedWeights =()=> {
    const p1 = {x:721, y:432}
    const p2 = {x:211, y:122}
    const p3 = {x:328, y:833}
    const p4 = {x:900, y:400}

    let trainedWeights;
    
   trainedWeights =  train(randomWeights,p1,team(p1))
   trainedWeights =  train(trainedWeights,p2,team(p2))
   trainedWeights =  train(trainedWeights,p3,team(p3))
   trainedWeights =  train(trainedWeights,p4,team(p4))

   return trainedWeights;
}

得到结果并不在我们weight(-1,1)取值范围内,

trainedWeights = 785.6063038318143,  -801.4601438564098
var html=`
    <svg width="${X_MAX}" height="${Y_MAX}">
        ${randomPoints.map(point=>
            `<circle 
                cx="${point.x}"
                cy="${point.y}"
                r="5"
                fill="${guess(trainedWeights(),point)===-1?'blue':'red'}"
                />`
        )}
        <line x1="0" x2="${X_MAX}" y1="0" y2="${Y_MAX}" stroke="purple"/>
    </svg>
`;

document.getElementById("app").innerHTML = html;

将我们训练好的结果 trainedWeights() 代替随机权重返回到图,我们发现图中点分布接近我们期望结果,蓝色和红色点大致都分布在线两侧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容