用 js 搭建神经网络

作者: zidea | 来源:发表于2019-07-11 07:23 被阅读30次
    MachineLearninginMarketing

    当下有关神经网络依旧很火,作为 web 前端人员或许并不了解 python ,平时我们接触算法也并不多,但是出于兴趣我们还想了解机器学习或深度学习。
    今天作为 web 开发我们更多注重视觉效果而不是神经网络内部结构,以及神经网络是如何构成和其内部机制。
    今天一切从简单开始,从一个简单分类问题开始,通过机器学习,让机器可以判断出在二维坐标系中某一点是在我们已知线的那一侧,来了解是如何使用 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,​​​​​
    

    更进步,我们需要一些随机点显示在我们屏幕上,下面代码实现生成一个随机点

    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;
    
    

    我们 team 将这条之间两次点进行划分不同的 team,然后通过验收将不同 team 点表示出来

    var team = point => point.x > point.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="${team(point)===-1?'blue':'red'}"
                    />`
            )}
            <line x1="0" x2="${X_MAX}" y1="0" y2="${Y_MAX}" stroke="purple"/>
        </svg>
    `;
    

    team 函数通过简单逻辑(规则)对随机点进行分类,平时我们会遇到很多分类问题,为了学习我们通常学习一件复杂事物也都是从简单开始,从简单到复杂。通过点的 x 和 y 值就可以进行判断,所以每一个点有两个特征(或者说标签)可以判断其的分类。

    实际中没有怎么简单,我们评价一个房源,对房源进行分类会有很多维度,多的我们无法通过想象来视觉化这个分隔曲面。

    好接下来我们就开始构建 AI 来模拟机器学习过程。

    权重是神经网络一个基本元素,我们可以简单想象 weight 就是一个状态,使我们神经元对某个输入感兴趣程度,也就是这个输入对结果影响程度。机器学习就是要推测出 weight 来进行判断。我们通过调整weight 然后对比计算结果和期望进行对比优化他们差值,不断循环这个过程来实现训练

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

    给出一个随机 Weight

    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() 代替随机权重返回到图,我们发现图中点分布接近我们期望结果,蓝色和红色点大致都分布在线两侧。

    相关文章

      网友评论

        本文标题:用 js 搭建神经网络

        本文链接:https://www.haomeiwen.com/subject/jwmkkctx.html