机器学习笔记1(网易课堂)

本文介绍了如何使用JavaScript结合动画演示,从基础的线性回归模型构建,到损失函数(曼哈顿和欧氏距离)、斜率与导数的应用,以及如何通过梯度下降法调整参数。实例展示了如何录入并绘制房屋数据,以及预测房价的过程和损失函数的计算与优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动画版机器学习

网易云课堂

JavaScript简易note

  1. 变量
    var applecount = 3;
    applecount = 5;
    console.log(“变量applecont的值是” + applecount);

  2. 对象
    var apple1 = {weight:1,price:2};
    var house = {area:85,price:705};
    console.log(“苹果的重量是” + apple1.weight + “斤”);
    apple1.price = 200;
    console.log(“苹果的售价是” + apple1.price + “元”);

  3. 数组
    var apples = [{weight:1, price:2},{weight:2, price:4},{weight:3, price:6];
    var answers = [2,3,4];

    console.log(“第一个苹果的重量是:” + apples[0].weight +“斤”);
    console.log(“第二个苹果的价格是:” + apples[1].price + “元”);

apples[0].price = 200;

  1. 判断
    console.log(“小李第一题回答是否正确?” + (answers[0] == apples[0].price));
    If(answers[0] == apples[0].price){
    console.log(“奖励”);
    }else{
    console.log(“惩罚”);
    }

  2. 循环
    for(var i = 0; i<3; i++){
    Console.log(“当前循环到第” + i + “个”);
    }

  3. 四则运算

线性回归模型

房屋售价(样本标签)=房屋单价×房屋面积(样本特征
+居间服务费
y=w×x+b(线性模型)

预测结果取值连续=>预测模型为回归模型
预测结果取值离散=>预测模型为分类模型

因此,房价的取值连续=>房间预测模型为线性回归模型

录入并绘制房屋样本数据

序号房子面积(单位:百平米)房子售价(单位:百万元)
10.857.05
21.038.6
31.1189.25
41.179.7
51.199.88
61.2510.35
71.30910.82
80.927.65
91.088.95
101.159.55

前7套房源数据作为训练样本集,后3套作为测试样本集。
训练样本集的代码定义如下:

var trainData = [{area:0.85,money:7.05},{area:1.03,money:8.6},
{area:1.118,money:9.25},{area:1.17,money:9.7},
{area:1.19,money:9.88},{area:1.25,money:10.35},
{ares:1.309,money:10.82}];

测试样本集的代码定义如下:

var testData = [{area:0.92,money:7.65},{area:1.08,money:8.95},
{area:1.15,money:9.55},{area:1.2,money:9.95}];

打印:

console.log("训练样本集中的第一个样本的面积特征是:" + trainData[0].area + "售价标签是:" + trainData[0].money);

绘制:

plot(trainData,{x:"area",y:"money"});

函数定义与调用

function yaohe(){
	console.log("买不了吃亏");
	console.log("买不了上当");
}
//上地店
yaohe();
//五道口店
yaohe();
//知春路店
yaohe();

个性化:

function yaohe(music,shopName){
	console.log("welcome!" + shopName);
	if(music == 1){
		console.log("播放背景音乐:朗格里格朗~");
	}else{
		console.log("播放背景音乐:咚咚锵~");
	}

}
//上地店
yaohe(1,"上地店");
//五道口店
yaohe(2"五道口店");
//知春路店
yaohe(2,"知春路店");

定义房价预测函数

function predict(x,w,b){
	var yhat = w*x + b;
	console.log("预测的房屋售价为:" + yhat);
}
predict(trainData[0].area,1,0);
//后续调整w,b

使用预测结果:

function predict(x,w,b){
	var yhat = w*x + b;
	return yhat;
}
var house1Predict = predict(trainData[0].area,1,0);
console.log("预测的第一个房屋售价为:" + house1Predict);
var house2Predict = predict(trainData[1].area,1,0);
console.log("预测的第二个房屋售价为:" + house2Predict);
//后续调整w,b

对比损失函数

yhat = w*x+b

  • L=|yhat-y| (曼哈顿距离)

  • L=(yhat-y)2(欧氏距离) √

找到合适的w,b => 梯度下降法

损失函数概述

上几节预测函数:

function predict(x,w,b){
	var yhat = w*x + b;
	return yhat;
}

还不知道预测函数中的w和b是多少,在找到w和b之前,应该知道怎么衡量w和b到底合不合格。假设现在有3个预测函数,对5个样本的预测结果如下:

序号样本标签(标准答案)第一个预测函数第二个预测函数第三个预测函数
110668
210998
3101098
4101198
5101478

现将数据录入:

var labels = [10,10,10,10,10];
var answers1 = [6,9,10,11,14];
var answers2 = [6,9,9,9,7];
var answers3 = [8,8,8,8,8];
console.log("5个样本的样本标签是:" + labels);

预测结果直接减去样本标签?

var loss = 0;
//labels.length表示labels数组中元素的个数,数组自带属性
for(var i = 0; i < labels.length; i++){
	loss1 = loss1 + answers1[i] - labels[i];
	loss2 = loss2 + answers2[i] - labels[i];
	loss3 = loss3 + answers3[i] - labels[i];
}
console.log("第一个预测函数的总误差是:" + loss1);//0
console.log("第二个预测函数的总误差是:" + loss2);//-10
console.log("第三个预测函数的总误差是:" + loss3);//-10

损失函数——曼哈顿距离

console.log("-2的绝对值是:" + Math.abs(-2));

曼哈顿:差值的绝对值作为损失大小
预测结果样本标签的绝对值

var loss = 0;
//labels.length表示labels数组中元素的个数,数组自带属性
for(var i = 0; i < labels.length; i++){
	loss1 = loss1 + Math.abs(answers1[i] - labels[i]);
	loss2 = loss2 + Math.abs(answers2[i] - labels[i]);
	loss3 = loss3 + Math.abs(answers3[i] - labels[i]);
}
console.log("第一个预测函数的总误差是:" + loss1);//10
console.log("第二个预测函数的总误差是:" + loss2);//10
console.log("第三个预测函数的总误差是:" + loss3);//10

损失函数——欧氏距离

console.log("-2的平方是:" + Math.pow(-2,2));
console.log("-2的立方是:" + Math.pow(-2,3));

欧几里得距离:差值的平方作为损失大小

var loss = 0;
//labels.length表示labels数组中元素的个数,数组自带属性
for(var i = 0; i < labels.length; i++){
	loss1 = loss1 + Math.pow((answers1[i] - labels[i]),2);
	loss2 = loss2 + Math.pow((answers2[i] - labels[i]),2);
	loss3 = loss3 + Math.pow((answers3[i] - labels[i]),2);
}
console.log("第一个预测函数的总损失是:" + loss1);//34
console.log("第二个预测函数的总损失是:" + loss2);//28
console.log("第三个预测函数的总损失是:" + loss3);//20 √

一般, 由于平方求导多一个2,会先乘一个1/2(让后面的梯度下降公式更加清晰):

var loss = 0;
//labels.length表示labels数组中元素的个数,数组自带属性
for(var i = 0; i < labels.length; i++){
	loss1 = loss1 + 1/2*Math.pow((answers1[i] - labels[i]),2);
	loss2 = loss2 + 1/2*Math.pow((answers2[i] - labels[i]),2);
	loss3 = loss3 + 1/2*Math.pow((answers3[i] - labels[i]),2);
}
console.log("第一个预测函数的总损失是:" + loss1);//17
console.log("第二个预测函数的总损失是:" + loss2);//14
console.log("第三个预测函数的总损失是:" + loss3);//10 √

利用斜率让线性函数值逐步下降

损失函数看作高度,将其中的参数变量看作水平方向的位置,只要知道损失函数的斜率,就可以通过调整参数,让损失函数下降。
斜率>0 :参数越小,损失函数越小
斜率<0 :参数越大,损失函数越小

斜率的定义

  1. 定义一个线性函数:
function linear(t){
	var s = 2*t + 1;
	return s;
}
console.log("在t=5处的函数值为:" + linear(5));
  1. 绘制:
plot(null, null, linear,{start:-5, end: 5});
  1. 得出斜率:
var diff = linear(6) - linear(5);
var sielv = diff/(6-5);
console.log("函数s=2*t+1斜率是:" + xielv);

斜率性质(函数值如何下降)

让函数值逐步下降:

var t = 5;
while(linear(t) > 0){
	t = t - 1;
	console.log("当前变量为:" + t + " 函数值为:" + linear(t));
}

图形演示下降过程:

var t = 5;
var points = [];
//每个数组都有push方法,用来将新元素追加到数组末尾
points.push([5,linear(5)]);
while(linear(t) > 0){
	t = t - 1;
	points.push([t,linear(t)]);
	console.log("当前变量为:" + t + " 函数值为:" + linear(t));
}
plot(points, null, linear);

换个函数:

function newLinear(t){
	var s = 8-2*t;
	return s;
}
var newT = 1;
var newPoints = [];
//每个数组都有push方法,用来将新元素追加到数组末尾
NewPoints.push([1,newLinear(1)]);

var newXieLv = (newLinear(6)-newLinear(5))/(6-5);
console.log("函数s=8-2t斜率为:" + newXieLv);

while(newLinear(newT) > 0){
	newT = newT + 1;
	newPoints.push([newT,newLinear(newT)]);
	console.log("当前变量为:" + newT + " 函数值为:" + newLinear(newT));
}
plot(newPoints, null, newLinear);

利用导数让非线性函数值逐步下降

导数的定义

function nonLinear(t){
	var s = t*t;
	return s;
}
console.log("在t=5处的函数值为" + nonLinear(5));

绘制:

//plot(null, null, nonLinear);
plot(null, null, nonLinear, {start:-5, end:5});

计算曲线函数上各点的导数?

var t = 5;
//var der = (nonLinear(5.01)-nonLinear(5))/(5.01-5);
//console.log("在t=5处的导数值近似等于:" + der);
console.log("在t=5处的导数值等于:" + 2*t);

导数性质(函数值如何下降)

当导数值大于0时,要减少变量t来让函数值下降。
当导数值小于0时,要增加变量t来让函数值下降。

var t = 5;
while(nonLinear(t) > 0){
	var der = 2*t;
	if(der > 0){
		t = t - 1;
	}else{
		t = t + 1;
	}
	console.log("当前变量t:" + t + "当前函数值:" + nonLinear(t));
}

图形演示下降过程:

var t = 5;
var points = [];
points.push([t,nonLinear(t)]);
while(nonLinear(t) > 0){
	var der = 2*t;
	if(der > 0){
		t = t - 1;
	}else{
		t = t + 1;
	}
	points.push([t,nonLinear(t)]);
	console.log("当前变量t:" + t + "当前函数值:" + nonLinear(t));
}
//plots(points, null, nonLinear);
plots(points, null, nonLinear,{start:-5, end:5});

换个起始点?

function train(t){
	var points = [];
	points.push([t,nonLinear(t)]);
	var times = 0;
	while(nonLinear(t) > 0 && times < 100 ){
		var der = 2*t;
		if(der > 0){
			t = t - 1;
		}else{
			t = t + 1;
		}
		points.push([t,nonLinear(t)]);
		times = times + 1;
		console.log("第" + times + "次时当前变量t:" + t + "当前函数值:" + nonLinear(t));
	}
	//plots(points, null, nonLinear);
	plots(points, null, nonLinear,{start:-5, end:5});
}
train(-3.5);

换步幅

function train(t,step){
	var points = [];
	points.push([t,nonLinear(t)]);
	var times = 0;
	while(nonLinear(t) > 0 && times < 100 ){
		var der = 2*t;
		if(der > 0){
			t = t - step;
		}else{
			t = t + step;
		}
		points.push([t,nonLinear(t)]);
		times = times + 1;
		console.log("第" + times + "次时当前变量t:" + t + "当前函数值:" + nonLinear(t));
	}
	//plots(points, null, nonLinear);
	plots(points, null, nonLinear,{start:-5, end:5});
}
train(-3.5, 0.5);
train(-3.8, 0.5);//?下节学习步长

学习步长的概念和作用

让函数值离最低点远时下降速度快,离最低点近时下降速度慢(快到最低点时减速)。
即离最低点时,让变量变化大一些;离最低点近时,让变量变化小一些。
而离最低点导数的绝对值较大,离最低点近的导数的绝对值较小。

导数大于0时,变量减去导数的绝对值;
导数小于0时,变量加上导数的绝对值。

即:
无论导数正负,只要让变量减去导数值,就可以让函数值下降。

但油门不能踩到底,为了避免震荡,需要在导数前乘以一个较小的系数
综上:
tnext = t - αds/dt
其中,α为
学习步长*。

yhat = w * x + b
L = (yhat - y)2
因此,L=(w * x + b - y)2
x:面积特征,y:真实售价,只要依据导数的性质调整w和b,就可以让损失函数逐步下降了。(下节偏导数和梯度下降法)

学习步长

function train(t,lr){//lr为学习步长
	var points = [];
	points.push([t,nonLinear(t)]);
	var times = 0;
	while(nonLinear(t) > 0.0001 && times < 100 ){
		var der = 2*t;
		//t = t - der;//油门踩到底
		t = t - lr*der;
		points.push([t,nonLinear(t)]);
		times = times + 1;
		console.log("第" + times + "次时当前变量t:" + t + "当前函数值:" + nonLinear(t));
	}
	//plots(points, null, nonLinear);
	plots(points, null, nonLinear,{start:-5, end:5});
}
train(5, 0.4);//t = t - 0.4*der
train(5, 0.5);//√更好
train(5, 1.1);//×不是越大越好

偏导数和梯度下降

yhat = w * x + b
L = (yhat - y)2

因此,L=(w * x + b - y)2
x:面积特征,y:真实售价,只要依据导数的性质调整w和b,就可以让损失函数逐步下降了。(偏导数和梯度下降法)
梯度方向:合力方向
通过沿着梯度的反方向来更新变量,来让函数值逐步下降的:
r = s -2t
dr/dt = -2
dr/ds = 1
tnext = t - dr/dt
snext = s - dr/ds

后面要加入学习步长

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值