当下有关神经网络依旧很火,作为 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() 代替随机权重返回到图,我们发现图中点分布接近我们期望结果,蓝色和红色点大致都分布在线两侧。
图
网友评论