首页 > 其他分享 >TypeScript版的吴恩达的机器学习课程练习-2

TypeScript版的吴恩达的机器学习课程练习-2

时间:2023-11-12 21:05:37浏览次数:32  
标签:featureData 吴恩达 TypeScript const feature shape 课程 tf data

这几天看完了逻辑回归相关的课程,听着的时候感觉还算顺利,但是在进行课程练习的过程中还是花费了较长的时间,因为我画出的图形和实际出题题目后面的图形有点不太一样,所以来来回回不断地调整参数。后面才发现和学习速度α以及梯度下降次数有很大的关系。


模型实现

具体的模型推到就不说了,具体推到过程在视频和相关的学习资料中已经说的很清楚了,那么直接通过TypeScript进行实现吧


假设函数

分为了三个函数,为了清晰拆分了三个函数,分别为HypothesisSigmoidPolynomial

// 实现的是1/(1+e^(-z))
async Sigmoid(pow: tf.Tensor<tf.Rank>) {
  const e = tf.fill([1, pow.shape[1] || 1], Math.E);
  const ones = tf.ones([1, pow.shape[1] || 1]);
  return ones.div(ones.add(e.pow(pow.mul(-1))));
}

// 实现的是θT*X
async Polynomial(feature: tf.Tensor<tf.Rank>, theta: tf.Tensor<tf.Rank>) {
  const ones = tf.ones([feature.shape[0], 1]);
  const data = tf.concat([ones, feature], 1);
  const powForE = theta.transpose().matMul(data.transpose());
  return powForE;
}

async Hypothesis(feature: tf.Tensor<tf.Rank>, theta: tf.Tensor<tf.Rank>) {
  return await this.Sigmoid(await this.Polynomial(feature, theta));
}


代价函数

因为题目中不需要再代价函数中实现lambda,所以这边就没写

  async Cost(
    feature: tf.Tensor<tf.Rank>,
    theta: tf.Tensor<tf.Rank>,
    y: tf.Tensor<tf.Rank>,
    lambda: number = 0
  ) {
    const yi = y.transpose();
    const h = await this.Hypothesis(feature, theta);
    const e = tf.fill([1, h.shape[1] || 1], Math.E);
    const ones = tf.ones([1, h.shape[1] || 1]);
    const a1 = yi.mul(-1).mul(h.log()); //-yi*log(h(xi))
    const a2 = ones.sub(yi).mul(ones.sub(h).log()); //(1-yi)*log(1-h(xi))
    let sumData = a1.sub(a2).sum();
    return sumData.div(feature.shape[0]).dataSync();
  }


梯度函数

这个方法实现的下降一次的方法,加入Lambdaθ进行正则化

  async Gradient(
    feature: tf.Tensor<tf.Rank>,
    theta: tf.Tensor<tf.Rank>,
    y: tf.Tensor<tf.Rank>,
    alpha: number,
    lambda: number = 0
  ) {
    const h = await this.Hypothesis(feature, theta);
    const ones = tf.ones([feature.shape[0], 1]);
    const featureData = tf.concat([ones, feature], 1);
    let sumData = h.transpose().sub(y).mul(featureData)
    let descent = sumData.sum(0, true).transpose().div(feature.shape[0])
    if (lambda > 0) {
      const thetaProcess = theta.mul(tf.zeros([1, 1]).concat(tf.ones([theta.shape[0] - 1, 1])));
      const data_Regularization = thetaProcess.mul(lambda / feature.shape[0])
      descent = descent.add(data_Regularization);
    }
    const data = theta.sub(descent.mul(alpha));
    return data;
  }


梯度下降

那么梯度下降就可以对梯度函数进行循环即可

  async GradientDescent(
    feature: tf.Tensor<tf.Rank>,
    alpha: number,
    theta: tf.Tensor<tf.Rank>,
    yi: tf.Tensor<tf.Rank>,
    iterations: number,
    lambda: number = 0
  ) {
    let rTheta = theta;
    for (let i = 0; i < iterations; i++) {
      rTheta = await this.Gradient(feature, rTheta, yi, alpha, lambda);
    }
    return rTheta;
  }


线性的逻辑回归

题目大搞意思就是你手上有历史的学生考分和是否能够顺利毕业之间的关系,需要你推导出模型来通过分数预测学生是否能够顺利毕业。


画点阵图

直接后台读出数据,返回给前端即可

  async data1_showData(ctx: Context) {
    const data = ReadData("./data/ex2data/ex2data1.txt");
    ctx.body = data;
  }


如何前端画线就不多说了,画出来的如下图所示

TypeScript版的吴恩达的机器学习课程练习-2_吴恩达

看到上面这个图可以知道,边界线可以用一条直线表示,那么模型可以是:

TypeScript版的吴恩达的机器学习课程练习-2_人工智能_02

TypeScript版的吴恩达的机器学习课程练习-2_AI开发_03TypeScript版的吴恩达的机器学习课程练习-2_AI开发_04


计算θ=[0,0]时候的损失值


直接调用代价函数就可以了,具体的θ就传[0,0]即可

  async data1_costValue(ctx: Context) {
    const _ex2Service = new ex2Service();
    const data = ReadData("./data/ex2data/ex2data1.txt");
    const theta = tf.zeros([3, 1]);
    const featureData = tf.tensor(data);
    const feature = featureData.slice([0, 0], [featureData.shape[0], (featureData.shape[1] || 1) - 1]);
    const y = featureData.slice([0, (featureData.shape[1] || 1) - 1], [featureData.shape[0], 1]);
    const cost = await _ex2Service.Cost(feature, theta, y);
    ctx.body = cost;
  }

最终可以看到计算得到的值为: 0.6931471824645996

画边界线

直接调用梯度下降,计算即可拿到下降后的θ

  async data1_GradientDescent(ctx: Context) {
    const _ex2Service = new ex2Service();
    const data = ReadData("./data/ex2data/ex2data1.txt");
    const thInit = tf.zeros([3, 1]);
    const featureData = tf.tensor(data);
    const feature = featureData.slice([0, 0], [featureData.shape[0], (featureData.shape[1] || 1) - 1]);
    const y = featureData.slice([0, (featureData.shape[1] || 1) - 1], [featureData.shape[0], 1]);
    let theta = await _ex2Service.GradientDescent(feature, 0.01, thInit, y, 200000);
    ctx.body = theta.dataSync();
  }


在前端根据返回的θ画出边界线即可

TypeScript版的吴恩达的机器学习课程练习-2_人工智能_05


非线性的逻辑回归


画点阵图

直接后台读出数据,返回给前端即可

  async data2_showData(ctx: Context) {
    const data = ReadData("./data/ex2data/ex2data2.txt");
    ctx.body = data;
  }


最终画出来的图如下

TypeScript版的吴恩达的机器学习课程练习-2_AI开发_06


我们看到图形可以判断是非线性的边界,而且根据题目的要求需要对自变量x1x2进行转换才行

TypeScript版的吴恩达的机器学习课程练习-2_AI开发_07

具体的转换方法如下

  async MapFeature(feature: Array<Array<number>>) {
    let data: Array<Array<number>> = [];
    for (let i = 0; i < feature.length; i++) {
      let e: Array<number> = [];
      for (let pow = 1; pow <= 6; pow++) {
        for (let j = 0; j <= pow; j++) {
          e.push(Math.pow(feature[i][0], j) * Math.pow(feature[i][1], pow - j));
        }
      }
      data.push(e);
    }
    return data;
  }


画出lambda=1时候的边界线

代码如下,最终返回边界线的坐标。由于没有找到合适的等高线方法,因此这边调用了我自己写的方法。

async data2_GradientDescent_Lambda1(ctx: Context) {
    const _ex2Service = new ex2Service();
    const data = ReadData("./data/ex2data/ex2data2.txt");
    const dataMap = await _ex2Service.MapFeature(data);
    const thInit = tf.zeros([28, 1]);
    const featureData = tf.tensor(data);
    const feature = tf.tensor(dataMap);
    const y = featureData.slice([0, (featureData.shape[1] || 1) - 1], [featureData.shape[0], 1]);
    let theta = await _ex2Service.GradientDescent(feature, 0.01, thInit, y, 50000, 1);


    var dataFor: Array<Array<number>> = [];
    for (let x1 = -1.2; x1 <= 1.2; x1 += 0.01) {
      for (let x2 = -1.2; x2 <= 1.2; x2 += 0.01) {
        dataFor.push([x1, x2])
      }
    }
    const dataForMap = await _ex2Service.MapFeature(dataFor);
    const dataForH: any = (await _ex2Service.Polynomial(tf.tensor(dataForMap), theta)).dataSync();
    const returnData = Contour(dataForH, -0.01, 0.01, -1.2, 1.2, -1.2, 1.2, 0.01);
    ctx.body = returnData

  }


前端实现方式就不贴代码了,具体的图如下所示

TypeScript版的吴恩达的机器学习课程练习-2_吴恩达_08


画出lambda=0时候的边界线

代码如下

lambda=1是一模一样的,只是参数不一样,另外具体的学习速度和梯度下降次数也慢慢试出来的

  async data2_GradientDescent_Lambda0(ctx: Context) {
    const _ex2Service = new ex2Service();
    const data = ReadData("./data/ex2data/ex2data2.txt");
    const dataMap = await _ex2Service.MapFeature(data);
    const thInit = tf.zeros([28, 1]);
    const featureData = tf.tensor(data);
    const feature = tf.tensor(dataMap);
    const y = featureData.slice([0, (featureData.shape[1] || 1) - 1], [featureData.shape[0], 1]);
    let theta = await _ex2Service.GradientDescent(feature,10, thInit, y, 50000, 0);
    //ctx.body = theta.dataSync();

    var dataFor: Array<Array<number>> = [];
    for (let x1 = -1.2; x1 <= 1.2; x1 += 0.01) {
      for (let x2 = -1.2; x2 <= 1.2; x2 += 0.01) {
        dataFor.push([x1, x2])
      }
    }

    const dataForMap = await _ex2Service.MapFeature(dataFor);
    const dataForH: any = (await _ex2Service.Polynomial(tf.tensor(dataForMap), theta)).dataSync();
    const returnData = Contour(dataForH, -0.1, 0.1, -1.2, 1.2, -1.2, 1.2, 0.01);
    ctx.body = returnData

  }


具体的图如下所示


TypeScript版的吴恩达的机器学习课程练习-2_AI开发_09


画出lambda=100时候的边界线

具体就不贴代码了,画出来的图如下所示

TypeScript版的吴恩达的机器学习课程练习-2_吴恩达_10


代码下载

将代码上传到了GitHub,想要的小伙伴直接下载吧 点击进入

标签:featureData,吴恩达,TypeScript,const,feature,shape,课程,tf,data
From: https://blog.51cto.com/pptong/8330725

相关文章

  • Shell 课程的课设分享
    程序功能用于实现一个综合应用程序,包括打印常用Shell命令手册、石头剪刀布游戏和加减乘除计算器。程序结构 运行截图         代码实现1#!/bin/bash2#一个综合应用脚本程序34#安装必备工具5functioninit{6case$......
  • 秦疆的Java课程:24 基础 数据类型扩展及面试题讲解
    1、整数扩展进制二进制数:0b开头八进制数:0开头十六进制数:0x开头publicclassDEMO1{publicstaticvoidmain(String[]args){//整数扩展:进制intA=10;intB=0b10;//二进制intC=010;//八进制intD......
  • 信息安全系统设计与实现课程第六章学习笔记
    一、知识点归纳1.信号和中断1.1进程概念进程是计算机中的基本执行单位,可以看作是一系列活动的集合。这些活动包括从事日常事务的人、在用户模式或内核模式下运行的Unix/Linux进程,以及执行机器指令的CPU。1.2中断中断是一种事件,用于通知进程需要进行某种处理,将进程从正常活......
  • Vite4+Typescript+Vue3+Pinia 从零搭建(2) - tsconfig配置
    tsconfig配置项目代码同步至码云weiz-vue3-template关于tsconfig的配置字段可查看其他文档,如typeScripttsconfig配置详解tsconfig.json文件修改如下:{"compilerOptions":{"target":"ESNext",//将代码编译为最新版本的JS"useDefineForClassFields":tr......
  • Vite4+Typescript+Vue3+Pinia 从零搭建(1) - 项目初始化
    项目初始化项目代码同步至码云weiz-vue3-template前提准备1.node版本Node.js版本>=12,如果有老项目需要旧版本的,推荐用nvm管理node版本。PSC:\Users\Administrator>nvm--version1.1.11PSC:\Users\Administrator>nvmlist*16.20.2(Currentlyusing64-bit......
  • Go Web开发进阶项目实战-Go语言实战课程体系,企业项目开发经验与技巧
    书接上回,上次我们搭建好了项目入口文件,同时配置了路由体系,接着就可以配置项目的模板了,这里我们采用Iris内置的模板引擎,事实上,采用模板引擎并不意味着前后端耦合,模板中的数据保持其独立性即可,也就是说模板的数据操作交互方式采用http接口请求的形式,Iris并不参与模板逻辑,只返回Jso......
  • 课程详情接口、所有章节接口、课程列表前端、课程详情前端、视频托管、Header.vue搜索
    课程详情接口#思路一:直接在之前写好的查询所有课程的视图类上,配置一个类即可classCourseView(GenericViewSet,CommonListModelMixin,CommonRetrieveModelMixin)返回的字段,跟详情,不太对应(详情中要求拿出所有章节和课时,但实际上只返回了4个课时)序列化类---》重......
  • 秦疆的Java课程笔记:22 基础 标识符和关键字
    关键字:abstract,assertboolean,break,bytecase,catch,char,class,const,continuedefault,do,doubleelse,enum,extendsfinal,finally,float,forgotoif,implements,import,instanceof,int,interfacelongnative,newpackage,private,protected,publicreturnstrictfp,sh......
  • 秦疆的Java课程笔记:23 基础 数据类型
    Java是一种强类型语言。或者称为强类型定义语言。要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用。一旦定义了一个变量,指定了某个数据类型,如果不经过转换的话,它就永远是这个类型了。好处是安全性高,相对的,速度就比较慢。弱类型语言,VBScript,JavaScript等,变量......
  • 秦疆的Java课程笔记:21 基础 注释
    平时写代码,代码量比较少的时候还能看懂自己写的,但当项目结构复杂起来,就需要用到注释。注释并不会被执行,是写给写代码的人看的,让别人更容易理解代码。注释是一个非常好的习惯。单行注释publicclassHelloWold{publicstaticvoidmain(String[]args){......