前端佬:机器学习?我也会啊!😎😎😎手“摸”手教你做个”自动驾驶“~

神经网络?人工智能?这些词应该都看腻歪了吧?想必还没有人不知道吧?

啥?不知道?

那.....别走😭😭😭😭,听我说!

前言

本篇幅主要是通过web,来做一个模拟的"自动驾驶"。

当然,这个只是提供一个大致的框架流程,逐步实现这么一个"自动驾驶",只是会有一些伪代码。

如果有更细致的讲解,呃,看有多少人需要,如果需要,请留一个支持专栏,到时候我给一个更详细的讲解。

预先准备

1、道路场景准备

"自动驾驶"嘛,首先就是道路的绘制。

道路的绘制,核心点点在于,先设定点,然后由点生成线,然后由线扩充道路的宽度。

具体伪代码如下:

js 复制代码
// 点的类
export default class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  .....其它绘制代码...
}

// 线的类
export default class Segment {
  constructor(startPoint, endPoint) {
    this.startPoint = startPoint;
    this.endPoint = endPoint;
  }
  .....其它绘制代码...
 }
 
 // 由线,生成多边形类以及优化外角为原型
 export default class Polygon {
      constructor(segments) {
        this.segments = segments;
        // 点位循环,加入线条中去
        for (let i = 1; i <= points.length; i++) {
          this.segments.push(new Segment(points[i - 1], points[i % points.length]));
        }
      }
  }

具体效果如下:

另外,小地图的绘制用于缩小整体的地图展示,有了点和线,基本都可以绘制。

PS:提示下哈,这些代码都可以由代码AI生成!

2、小汽车准备:

有了以上的道路,那么就得有像样的车子在道路上。

车子的功能需要满足这些来模拟真实的车子,比如:

  • 支持前、后、前左转弯、前右转弯,后左转弯。后右转弯;

  • 模拟摩擦力,向前或者向后的动力,如果向前或者前后的动力不再持续,则速度会降至0;

效果如下(以下由键盘的↑↓←→键控制):

然后,我们再加上与道路交互,当碰撞到道路,速度停止,不再移动;

有一说一,我这种手残的控制,基本都能撞墙。😭😭😭😭😭😭😭😭😭😭😭😭。。

上"动力"

1、汽车上"雷达"

好了,有了上面的基本材料,现在需要给汽车的一个感知能力。这边是在汽车的前方,增加一个所谓雷达感知。

这里的"雷达",是指可检测汽车与周边环境的距离,如下图:

其中黑色为安全距离外,黄色为安全距离内。

现实生活中,雷达当然不是这样的,有兴趣的可以自行搜索下。

扯题外话,现实中,让汽车有感知周围环境的能力,目前有两种方式主流模式:一个是雷达成像,还有一种为摄像头直接探测;

2、上"智能"--神经网络算法

这边暂时跳过项目,先了解下神经网络基础算法,如下图示:

神经网络最基础的算法,就是分输入层=》隐藏层=》输出层。

输入层输入最开始定义的数据,然后每一个点都链接隐藏层。其输出的值,就是∑输入值x每个对应点的权重的总和,如果大于或者小于某一个偏置层,则会给隐藏层设置对应的输入值。

经过上述所有层级,最后会有输出数据。

因为我们自动驾驶需要前、后、左、右的方向控制,这里设置的输出就会是四个值。

不懂没有关系,直接上源码。

js 复制代码
import { lerp } from '../utils/index.js';

export class NeuralNetwork {
  constructor(neuronCounts) {
    this.levels = [];
    // 获取层级
    for (let i = 0; i < neuronCounts.length - 1; i++) {
      this.levels.push(new Level(neuronCounts[i], neuronCounts[i + 1]));
    }
  }
  // 返回层级输出
  static feedForward(givenInputs, network) {
    let outputs = Level.feedForward(givenInputs, network.levels[0]);

    for (let i = 1; i < network.levels.length; i++) {
      outputs = Level.feedForward(outputs, network.levels[i]);
    }
    return outputs;
  }

  // 从最佳策略中,变更值
  static mutate(network, amount = 1) {
    network.levels.forEach((level) => {
      for (let i = 0; i < level.biases.length; i++) {
        level.biases[i] = lerp(level.biases[i], Math.random() * 2 - 1, amount);
      }
      for (let i = 0; i < level.weights.length; i++) {
        for (let j = 0; j < level.weights[i].length; j++) {
          level.weights[i][j] = lerp(
            level.weights[i][j],
            Math.random() * 2 - 1,
            amount,
          );
        }
      }
    });
  }
}

export class Level {
  constructor(inputCount, outputConut) {
    this.inputs = new Array(inputCount);
    this.outputs = new Array(outputConut);
    // 偏差值,每个输出神经元都有一个偏差值
    // 高于该值它将触发这个输出
    this.biases = new Array(outputConut);

    // 权重值
    // 每一条输入,都对应很多条输出,每个输出都有对应的权重值
    this.weights = [];

    for (let i = 0; i < inputCount; i++) {
      this.weights[i] = new Array(outputConut);
    }

    Level.#randomize(this);
  }

  // 随机数据
  static #randomize(level) {
    for (let i = 0; i < level.inputs.length; i++) {
      for (let j = 0; j < level.outputs.length; j++) {
        level.weights[i][j] = Math.random() * 2 - 1;
      }
    }

    for (let i = 0; i < level.biases.length; i++) {
      level.biases[i] = Math.random() * 2 - 1;
    }
  }

  // 反馈
  static feedForward(givenInputs, level) {
    // console.log(level)
    for (let i = 0; i < level.inputs.length; i++) {
      level.inputs[i] = givenInputs[i];
    }
    for (let i = 0; i < level.outputs.length; i++) {
      let sum = 0;
      // 计算每一条线的积分,输入加权重
      for (let j = 0; j < level.inputs.length; j++) {
        sum += level.inputs[j] * level.weights[j][i];
      }

      // 判断,如果大于偏差值,则输出结果
      if (sum > level.biases[i]) {
        level.outputs[i] = 1;
      } else {
        level.outputs[i] = 0;
      }
      // level.outputs[i] = Math.tanh(sum + level.biases[i]);
    }

    return level.outputs;
  }
}
3、动起来

好了,算法也有了,细心的朋友看上面的代码,一定知道。上面给与各个权重都是有一个初始的随机值的。

这个,就是为了方便给与每项的权重和偏置值都有一个初始种子,因为我们需要这个随机的值去驱动我们的车。

我随机生成了一个,如下:

很明显。这随机碰运气的话,得到的模型数据并不好。

那么如何将这个汽车训练的越来越好呢?

择优-遗传算法

不知道前端佬有没有看过火影忍者,里面的主人公会一种影分身。而这个影分身用在学习上,非常的变态。假如你有1000个影分身,同时去学习一个东西,而要其中有一个会了,那么基本主人公自己就会了。

基于这种方法,我们可以将汽车随机生成1000个,那基本就有1000个模型。我们让这1000个同时跑起来,选择其中一个最好的就行了。如下图(时间会有点长):

结果

最终,我大致搞了这么一个模型,效果如下:

如果有时间的话,还可以加入各种策略,比如红绿灯,人行道,或者其他车辆。感兴趣的可以自己动手试试!

前端佬们,机器学习之路,还是不错的吧?

哈哈~

相关推荐
Liquad Li2 小时前
Angular 面试题及详细答案
前端·angular·angular.js
用户21411832636023 小时前
首发!即梦 4.0 接口开发全攻略:AI 辅助零代码实现,开源 + Docker 部署,小白也能上手
前端
Caaacy_YU3 小时前
多模态大模型研究每日简报【2025-09-10】
论文阅读·人工智能·深度学习·机器学习·计算机视觉
gnip4 小时前
链式调用和延迟执行
前端·javascript
SoaringHeart5 小时前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.5 小时前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频
Dragon Wu5 小时前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
Jinuss5 小时前
Vue3源码reactivity响应式篇之watch实现
前端·vue3
YU大宗师5 小时前
React面试题
前端·javascript·react.js