以下均为来自中国大学mooc 游戏引擎原理及应用时的学习笔记,不含商用,仅供学习交流使用,如果侵权请联系作者删除。

文章目录

  • 8.1 自动寻路
  • 8.2 巡逻
  • 8.3 视野
  • 8.4 自动攻击
  • 8.5 追踪
  • 8.6 机器学习

8.1 自动寻路


dos操作时代的人工智能


英雄无敌3这样的回合策略制游戏

红警这样的即时战略很考虑人工智能






我们先建立如图所示的物体

并将其的属性设置为静态。因为将来的导航物体需要在这些物体上运动,这些物体只有成为静态物体,才能被烘焙成导航网络。

接下来调出这个窗口


我们可以在导航这里看到有三个是设定好的,分别是可以走,不可走和跳跃,然后右边是开销
也可以添加自定义的区域然后进行设置

这些取区域和agent配合设置可以达到特定的效果
agent里面可以设置区域遮蔽,让角色不能在某些特定的区域中移动,以此来区别对待敌人

object可以对选中的物体进行导航的相关设置


如果点选上navigation static 则非静态物体也会被烘培

接下来我们看看bake

将下面这几个参数调整成合适的,并进行烘培,可以看到效果如图,蓝色部分为可以行走的区域

然后添加一个被导航的物体,我们创建一个胶囊体,并给他添加上被导航的代理体
写入以下脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class navi : MonoBehaviour
{private NavMeshAgent agent;// Start is called before the first frame updatevoid Start(){agent = GetComponent<NavMeshAgent>();}// Update is called once per framevoid Update(){if (Input.GetMouseButton(0)){RaycastHit hit;if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hit, 100)){//这条语句完成了两个事情 一个是发射出一条射线,(如果有射线则进入if)并且把这条语句out 也就是输出给hit,查询多远的距离呢,是100个单位agent.destination = hit.point;}}}
}

拖拽给物体便可以看到物体会自动走到鼠标点击的地方

有时候平台无法跳上去 我们可以使用jump功能


如图所示我们新建两个空物体,并且将两个空物体置于平台底部和高处

我们给它添加一个组件


然后移动到这上面
这时候再运行游戏场景便可以使得它进行跳跃

接下来介绍一下动态的阻挡物
如果我们直接添加一个物体(非静态) 那么这个物体是不会影响物体自动寻路的


直接通过 无法阻止

但是路过我们给胶囊体设置为刚体 则物体在寻路的时候不会绕开这个物体而寻找其他路线,而是直接遵循两点之间线段最短的路来走,但是此时就会出现这个物体一直撞着这个物体而很难走开,就一直日墙怼墙

为了让这种物体也能参与寻路的影响,我们给这个方块添加一个这样的组件


这时候这个物体就会阻止导航体穿过去,起到阻挡的作用

8.2 巡逻

我们还是用之前的地形 别忘记对可以走路的区域进行烘培
然后创建一个空物体 下面有四个空物体 分别用来表示位置

然后我们创建一个胶囊物体 给他带上nav mesh agent的这个导航组件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AIpartrol : MonoBehaviour
{// Start is called before the first frame updatepublic float patrolSpeed = 2f;public float patrolWaitTime = 1f;public Transform patrolWayPoints;private NavMeshAgent agent;private float patrolTimer;//这个用来记录当敌人达到路径点的时候 停留时间是多久private int wayPointIndex;//记录当前目标点是哪个路径点void Start(){agent = GetComponent<NavMeshAgent>();}// Update is called once per framevoid Update(){Patrolling();}void Patrolling(){agent.isStopped = false;agent.speed = patrolSpeed;if (agent.remainingDistance<=agent.stoppingDistance)//由于可能这个物体并不是一分不差的到目的点的,我们可以用用一个范围表示冗余//当到达目的点时开始计算时间{patrolTimer += Time.deltaTime;if (patrolTimer >= patrolWaitTime)//如果等待时间已满,则进入下一个点{if (wayPointIndex == patrolWayPoints.childCount - 1){wayPointIndex = 0;}else{wayPointIndex++;}patrolTimer = 0;//由于切换完成 所以我们将这个time归零计算}//这里没有else 是因为如果没=等待时间没满则什么都不会做 只是单单的增加事件}else{patrolTimer = 0;}agent.destination = patrolWayPoints.GetChild(wayPointIndex).position;//Getchild方法可以获得这个东西的子物体//括号里面跟的是下标}}

8.3 视野

以前两节的内容为基础,我们给Enemy添加一个子物体空物体,来表示其碰撞体积的组件


然后注意要给这个box collider添加上trigger的组件
然后写下以下代码 将这个代码挂接到这个子物体而不是这个Enemy上
因为发生OnTrigger函数的应该是那个碰撞的空物体,如果挂接到母物体上,虽然会进入OnTrigger函数但是无法检测到if (other.gameObject == Player)这条语句

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class View : MonoBehaviour
{public float fieldOfViewAngle = 120f;//视角范围public bool playerInSight;//public Vector3 personalLastSight;//用来表示最后主角所在的位置public static Vector3 resetPos = Vector3.back;BoxCollider col;//这个组件上的碰撞检测器组件public GameObject Player;// Start is called before the first frame updatevoid Start(){col = GetComponent<BoxCollider>();//player = GameObject.FindGameObjectWithTag("Player");//除了可以用这个方法还可以使用public在游戏界面,然后将物体拖拽进来的方法//if(player.tag=="Player") Debug.Log("There is a player");personalLastSight = resetPos;//Debug.Log("Start");//为了看游戏执行的情况设置的调试语句}// Update is called once per framevoid Update(){}private void OnTriggerStay(Collider other){Debug.Log("OnTriggerStart");if (other.gameObject == Player){Debug.Log("PlayerInTrigger");playerInSight = false;Vector3 direction = other.transform.position - transform.position;//建立一个位置差的向量float angle = Vector3.Angle(direction, transform.forward);//以敌人的正前方和那个位置//差向量来获得角度//Debug.Log(angle);if (angle < fieldOfViewAngle * 0.5f)//如果说这个角度是在敌人开阔视野120度以内的话 说明进入视野范围内{Debug.Log("InSightStart");RaycastHit hit;//但是在视野范围内不代表能看到 因为可能会被障碍物挡住,我们需要//发出一条射线,然后判断射线能否打到玩家身上,如果可以说明能被看见if (Physics.Raycast(transform.position,direction.normalized,out hit,col.size.z))//以transform.positon代表发射的起点,direction代表发射的方向,normalized代表单位化,out hit代表将这条射线输出到hit,col.size.z代表长度{if (hit.collider.gameObject == Player){Debug.Log("I saw the player!");playerInSight = true;personalLastSight = Player.transform.position;}}}}}private void OnTriggerExit(Collider other)//如果玩家出去了那个碰撞体就代表无法被看见{if (other.gameObject == Player){playerInSight = false;}}
}

然后当player进入敌人的视野的时候,就会在console提示“I saw the player!”

8.4 自动攻击

我们还是以上面的场景为基础,然后我们新建一个子弹的预制体,并给它添加上几个组件

然后给球添加一个恒力

接下来我们要给子弹写一个脚本 当子弹碰到玩家的时候 销毁子弹和玩家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AIEnemyBullet : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}private void OnTriggerEnter(Collider other){if (other.gameObject.tag == "Player"){Destroy(other.gameObject);Destroy(gameObject);}}
}

接下来我们需要给敌人的巡逻脚本中添加如下的函数

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class patrol : MonoBehaviour
{// Start is called before the first frame updatepublic float patrolSpeed = 2f;public float patrolWaitTime = 1f;public Transform patrolWayPoints;private NavMeshAgent agent;private float patrolTimer;//这个用来记录当敌人达到路径点的时候 停留时间是多久private int wayPointIndex;//记录当前目标点是哪个路径点//接下来这里是和射击有关的函数public float shootRotSpeed = 5f;public float shootFreeTime = 2f;//枪的冷却时间public float shootTimer = 0f;//时间计数器private View enemySight;//这个是之前那个视野的组件,用它来得到当前玩家是否在视野中public Rigidbody bullet;//我们需要子弹这个预制体 在发射的时候实时生成出来 因此需要获得这个预制体private Transform player;bool chase;//追踪状态void Start(){agent = GetComponent<NavMeshAgent>();enemySight = transform.Find("ViewRange").GetComponent<View>();//获得viewrange这个组件上的View这个脚本//ViewRange是敌人的子物体 就是那个空物体然后具有trigger和体积 表示视野范围的物体,而view是这个子物体的脚本player = GameObject.FindGameObjectWithTag("Player").transform;//获得物体}// Update is called once per framevoid Update(){if (enemySight.playerInSight){Shooting();}else if (chase){//追踪}else Patrolling();}void Shooting(){Vector3 lookPos = player.position;//玩家的位置保存下来lookPos.y = transform.position.y;//将射出枪的位置改为和玩家一样的高度//避免在射击的时候还有抬头和点头的情况出现Vector3 targetDir = lookPos - transform.position;//发射的方向就是目标减去当前的位置//但是发射的时候 我们需要先转到我们看的方向transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetDir), Mathf.Min(1,Time.deltaTime*shootRotSpeed));//球面线性插值//Min函数是在两者间去最小的  一个是1 另外一个就是旋转的速度乘以时间//到1的时候就完全转过去了,否则它就是慢慢的过渡过去agent.isStopped = true;//因为我们要射击 所以此时要停下来//接下来判断此时转过去的角度是否达到了适合的角度//如果说if (Vector3.Angle(transform.forward, targetDir) < 2){if (shootTimer>shootFreeTime)//判断时间间隔是否大于冷却时间了{Instantiate(bullet, transform.position, Quaternion.LookRotation(player.position - transform.position));//上面的第二个参数应该使用枪的位置而不是人的位置会更准确一些//使用四元数的方法 lookrotation 把一个向量转变为四元数,那么这个向量就是朝向的向量shootTimer = 0;}shootTimer += Time.deltaTime;}}void Chasing(){}void Patrolling(){agent.isStopped = false;agent.speed = patrolSpeed;if (agent.remainingDistance <= agent.stoppingDistance)//由于可能这个物体并不是一分不差的到目的点的,我们可以用用一个范围表示冗余//当到达目的点时开始计算时间{patrolTimer += Time.deltaTime;if (patrolTimer >= patrolWaitTime)//如果等待时间已满,则进入下一个点{if (wayPointIndex == patrolWayPoints.childCount - 1){wayPointIndex = 0;}else{wayPointIndex++;}patrolTimer = 0;//由于切换完成 所以我们将这个time归零计算}//这里没有else 是因为如果没=等待时间没满则什么都不会做 只是单单的增加事件}else{patrolTimer = 0;}agent.destination = patrolWayPoints.GetChild(wayPointIndex).position;//Getchild方法可以获得这个东西的子物体//括号里面跟的是下标}}

然后便可以看到敌人会向玩家进行射击

//但是上面有几个缺陷
首先射出子弹的位置应该是枪的位置而不是人的位置
还有射枪的冷却时间不应该是在敌人准备射击中才增加的 应该是在时时刻刻都增加 因此应该把shootTimer += Time.deltaTime;这条语句放到update函数当中

代码中的remaining distance解释:

在《Unity官方案例精讲》里面提到可以用remainingDistance来判断移动是否结束,remainingDistance也就是(距离终点)剩余移动距离,让它跟stopingDistance(结束距离)进行比较

8.5 追踪

(下面会出现的东西

Vector3.sqrMagnitude 是指长度的平方,也就是Vector3.magnitude的平方

计算向量大小的平方会比计算向量的大小要快很多,因为向量的大小由勾股定理得出,所以有开方操作,如果只是单纯的比较两个向量的大小,可以使用sqrMagnitude会快很多。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class patrol : MonoBehaviour
{// Start is called before the first frame updatepublic float patrolSpeed = 2f;public float patrolWaitTime = 1f;public Transform patrolWayPoints;private NavMeshAgent agent;private float patrolTimer;//这个用来记录当敌人达到路径点的时候 停留时间是多久private int wayPointIndex;//记录当前目标点是哪个路径点//接下来这里是和射击有关的函数public float shootRotSpeed = 5f;public float shootFreeTime = 3f;//枪的冷却时间public float shootTimer = 0f;//时间计数器private View enemySight;//这个是之前那个视野的组件,用它来得到当前玩家是否在视野中public Rigidbody bullet;//我们需要子弹这个预制体 在发射的时候实时生成出来 因此需要获得这个预制体private Transform player;bool chase;//追踪状态public float chaseSpeed = 5f;//追踪的速度public float chaseTimer = 0;//等待时间的计数器public float chaseWaitTime = 3.5f;//追踪完后等待的时间private float sqrPlayerDist = 2f;//用平方表示距离 追踪到敌人附近的时候 //会保持一定距离 也就是彼此间对峙的距离 而不是就直接贴脸追到脸上void Start(){agent = GetComponent<NavMeshAgent>();enemySight = transform.Find("ViewRange").GetComponent<View>();//获得viewrange这个组件上的View这个脚本//ViewRange是敌人的子物体 就是那个空物体然后具有trigger和体积 表示视野范围的物体,而view是这个子物体的脚本player = GameObject.FindGameObjectWithTag("Player").transform;//获得物体}// Update is called once per framevoid Update(){shootTimer += Time.deltaTime;if (enemySight.playerInSight){Shooting();//Chasing();如果想要在进入视野的时候不仅是停下来射击,而且还会继续追逐的话,我们则取消注释这个函数chase = true;//如果曾经进入了视野,则将追踪设置为true}else if (chase)//如果下次没有进入到上面到insight 说明目标丢失,此时则会进入巡逻状态,//然后追踪设置为false,但是如果巡逻的时候再次进入视野,则会重新触发上面那个函数{Chasing();}else Patrolling();//在这里我们可以看到 通过在update中设置三种状态,一种是进入视野的状态,然后如果进入视野的话//则会开启追踪状态的选择,如果下次没进入第一个状态则会进入第二个状态//在第二个状态:追踪状态的时候,如果追踪失败,则会将这个状态置false//那么如果上面两种状态都没进去,则会自动进入巡逻状态//要注意的是Update的随着时间会不断重新执行的,因此我们只需要设置进入状态的条件即可,然后在执行update//的时候便会重新进入新的新的状态了}void Shooting(){Vector3 lookPos = player.position;//玩家的位置保存下来lookPos.y = transform.position.y;//将射出枪的位置改为和玩家一样的高度//避免在射击的时候还有抬头和点头的情况出现Vector3 targetDir = lookPos - transform.position;//发射的方向就是目标减去当前的位置//但是发射的时候 我们需要先转到我们看的方向transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetDir), Mathf.Min(1,Time.deltaTime*shootRotSpeed));//球面线性插值//Min函数是在两者间去最小的  一个是1 另外一个就是旋转的速度乘以时间//到1的时候就完全转过去了,否则它就是慢慢的过渡过去agent.isStopped = true;//因为我们要射击 所以此时要停下来//接下来判断此时转过去的角度是否达到了适合的角度//如果说if (Vector3.Angle(transform.forward, targetDir) < 2){if (shootTimer>shootFreeTime)//判断时间间隔是否大于冷却时间了{//Instantiate(bullet, transform.position, Quaternion.LookRotation(player.position - transform.position));//上面的第二个参数应该使用枪的位置而不是人的位置会更准确一些//使用四元数的方法 lookrotation 把一个向量转变为四元数,那么这个向量就是朝向的向量shootTimer = 0;}}}void Chasing(){agent.isStopped = false;Vector3 sightingDeltaPos = enemySight.personalLastSight - transform.position;//获得巡逻的物体应该走的方向向量if (sightingDeltaPos.sqrMagnitude > sqrPlayerDist)//如果这个距离大于设定好的阈值的话则需要继续追踪//为什么要设置这个if如果这个距离大于设定好的阈值的话则需要继续追踪呢?是因为在这里Update是一个一帧一次的函数//整个追击的过程是由很多帧 也就是执行了很多次Chasing函数才实现的,而不是一次函数就能完成,因此需要每一帧都不断重新判定是否//其次 这个阈值是什么呢 就是追踪结束时候,玩家与敌人设置的距离,如果达到了这个距离 则不会再往前走//可以理解为拿着手枪追杀敌人的时候,就算是对峙的时候,也会需要说离开一段距离然后开枪进行对峙,而不是直接贴脸//(当阈值设置很小的时候就等于贴脸了)//但是实际执行起来发现不是这样子 为什么呢?是因为如果进入视野的时候,我们不会执行追逐而是执行停下来射击的函数,//所以说还没达到对峙距离的阈值则会进入视野{agent.destination = enemySight.personalLastSight;//设定目的地为最后一次出现的地方}agent.speed = chaseSpeed;//速度由巡逻速度切换到追踪速度if (agent.remainingDistance <= agent.stoppingDistance)//最终到达目的地时//reaminingDistance是导航体自带的函数,是计算与目的地的距离的值//为了防止比如说旁边有个东西卡住了目的地的左边,这时候则会出现物体永远无法到达目的地的情况,我们设置了与目的地相比 允许的误差冗余{chaseTimer += Time.deltaTime;if (chaseTimer >= chaseWaitTime){chase = false;//如果超过等待时间,则自动结束追踪状态chaseTimer = 0f;}}else{chaseTimer = 0;}}void Patrolling(){agent.isStopped = false;agent.speed = patrolSpeed;if (agent.remainingDistance <= agent.stoppingDistance)//由于可能这个物体并不是一分不差的到目的点的,我们可以用用一个范围表示冗余//当到达目的点时开始计算时间{patrolTimer += Time.deltaTime;if (patrolTimer >= patrolWaitTime)//如果等待时间已满,则进入下一个点{if (wayPointIndex == patrolWayPoints.childCount - 1){wayPointIndex = 0;}else{wayPointIndex++;}patrolTimer = 0;//由于切换完成 所以我们将这个time归零计算}//这里没有else 是因为如果没=等待时间没满则什么都不会做 只是单单的增加事件}else{patrolTimer = 0;}agent.destination = patrolWayPoints.GetChild(wayPointIndex).position;//Getchild方法可以获得这个东西的子物体//括号里面跟的是下标}}

如果想要在玩家进入视野的时候不仅是停下来射击还有追逐的话 可以在update的进入视野的选项中添加Chasing函数

发现意外有趣的一点是对于追踪函数,如果稍作修改,便可以模拟出使得其变成小鸭子找妈妈的跟屁虫的感觉

首先将产生子弹预制体的函数取消
然后设置进入可以穿过障碍物来发射射线(这是为了防止跟在玩家后面的第一个物体会挡住后面物体的视线导致无法跟踪到的情况,应该还会有更好的办法进行优化设置的


一个小tips 如果暂时不想使菜单栏中的物体上场但又不想消除的话可以这样:取消选中该物体

又是一个总结的小tips
在游戏运行到一半的时候暂停 然后实时的修改代码的话 那会对游戏产生影响吗?
实际测试是没有产生影响 这和修改游戏内物体的位置大小还有参数都不太一样,实时修改位置大小和参数即时产生影响

还有一个小tips
想要通过修改参数看游戏游戏的变化的时候 可以直接给这个变量public然后就可以放到旁边通过实时修改值来判断游戏的变化

还有一点我们可以发现的是,当敌人追逐到这个这个空盒子(表示视野范围)的界限的时候则不会再继续往前走了

但是以上的追踪函数都有一个很大的缺陷,就是当敌人追逐到玩家最后出现的位置的时候,敌人不会进行自动转向,(也就是摇头查看周围的环境情况),只会看头所朝向的那个方向,如果玩家突然转变方向,虽然此时还在敌人的附近,但是不在敌人的forward方向的话,则敌人无法探测到(明明只需要敌人稍微转头就能看到了)这个方法的话有待以后优化吧。

还有个缺陷就是当人物走到敌人身后甚至贴上去的时候 按理来说也应该被发现了 然后此时敌人应该要转身追逐
但是由于本函数只追逐眼前的敌人,因此之后可能需要通过设置当玩家在敌人附近的时候就会转身追逐的函数吧

又发现了一个缺陷:当物体第一次离开视野时候,Chase Timer也就是等待时间的计数器会不断增加,可是当物体再次进入视野的时候,Chase
Timer不会自动清零,意味着下次继续计算等待时间的计数器的时候会再次从上一次开始,比如我原来等待了3秒,等待时间上限是5秒,那么下次我再次遇见然后再次玩家逃开的时候,等待时间计数器会从3秒开始计算,那么再等待两秒它就会自动返回巡逻了


说实话这里还是有点没搞懂,红框里是原来我自己写的解析,我以为那个对峙距离,但是实际测试后发现对峙距离是敌人的碰撞检测的体积的那个距离,所以这个
if (sightingDeltaPos.sqrMagnitude > sqrPlayerDist)
这个语句到底代表什么意思我还是有点没搞清楚,有待日后回来修正吧

8.6 机器学习






通过下载插件MLagent,还可以通过Ptyhon api对agent或者智能体进行训练

机器学习功能unity封装的比较好,学习起来不是很难
但是需要几个准备工作

首先下载这个安装包



需要把这些克隆下来到本地

然后编辑环境变量


建立好虚拟环境后输入这行命令查看配置

输入这行命令,查看前面是否有ml-agents 有的话说明激活了

把路径设置到克隆下来的路径里

下载第三方的安装包

注意要在子文件夹上进行安装


然后检查一下是否都安装好了

使用unity进入github示例工程 运行
可以看到这些盒子正在学习如何平衡小球

可以看到命令提示符这里

最后一行可以看到学习后的文件的存放地址:

其实这个unity包中里也有自带学习后的文件,将其放入

也可以将我们自己刚才学习好的文件放到指定目录下,然后使用这个文件

接下来可以可以自己新建一个模型并对它训练
创建一个新场景 然后创建空物体 为其挂接这个脚本

创建一个立方体和小球

并把正方体改名叫agent

为小球挂接刚体组件

为立方体挂接这三个脚本

观察脚本这里可以看到有8个浮点数

所以这个参数需要设置为8

并且修改这几个参数

这里需要将小球拖拽过来

进入cmd窗口,进入指定目录并且进入训练的环境

注意这里的名字并不需要与unity里面任何物体的名字相同

按下回车后看到unitylogo则代表进入环境成功,然后可以开始运行游戏


游戏运行时可以看到命令行窗口如图 它会显示当前训练的结果如何,小球的得分怎么样

Unity结束运行时,它便会把文件保存下来
训练完毕后便可以在cube的这个组件下挂接好学习好了的模型


接下来运行就可以看到方块按照学习好的模型,努力的平衡小球了。

但是由于实际不够长,学习的模型也不够多所以成果可能并不太好

【Unity入门教程】 第八章 人工智能【中国大学MOOC游戏引擎原理及应用】相关推荐

  1. 人工智能和python毕业设计题目_Python与人工智能-中国大学mooc-题库零氪

    Python与人工智能 - 中国大学mooc 已完结  451 第1周 课后作业 1.Q4 Conditional Probabilities Select all of the following ...

  2. python好学吗mooc中文网-Python与人工智能-中国大学mooc-题库零氪

    Python与人工智能 - 中国大学mooc 已完结  116 第1周 课后作业 1.Q4 Conditional Probabilities Select all of the following ...

  3. 笔记:中国大学MOOC课程《程序设计入门——C语言》编程练习

    笔记:中国大学MOOC课程<程序设计入门--C语言>编程练习 第7周 数组运算 1 多项式加法 第8周 指针与字符串 2 GPS数据处理 第7周 数组运算 1 多项式加法 题目内容: 一个 ...

  4. 中国大学MOOC C语言程序设计入门 第8周编程练习第二题 GPS数据处理

    中国大学MOOC C语言程序设计入门 第8周编程练习第二题 GPS数据处理 题目内容 解题思路 这个题的题目真的是我学习C语言以来见过的最长的题目了,很多人的第一感觉可能是无从下手,所以让我们先来整理 ...

  5. 中国大学MOOC胡浩基的机器学习第二章(支持向量机)兵王问题python版本——在python上初步使用libsvm

    在中国大学MOOC上看了胡浩基的机器学习课程,完全面向入门人群感觉挺好.其中有关原理的部分讲的很细.(虽然有几个细节我还是没懂.......)其中在第二章的例题兵王问题中课程只给了MATLAB的版本. ...

  6. 中国大学mooc上的python-Python程序设计及应用(上)

    spContent=曾有人说过,没有什么比计算机编程更无处不在的影响着21世纪,而21世纪必将是人工智能大展拳脚的时代,Python作为人工智能首选的编程语言备受欢迎.本课程从零基础出发,用上篇基础加 ...

  7. 中国大学 MOOC 课程Python语言程序设计 (第11期)测试答案(1-5周)

    中国大学 MOOC 课程Python语言程序设计 (第11期)测试答案(1-5周)  Lan   2020-05-03 14:21   369 人阅读  0 条评论 感谢中国大学MOOC提供的学习平台 ...

  8. python语言程序设计是什么课文_中国大学MOOC有哪些优质课程?

    说到学习,相信很多人囤了一堆自学网站吧?囤完之后,是不是依然不知道要学什么? 因为免费的网络课程,质量参差不齐,试错成本太高. 所以小叶子帮大家做了这样一件事,直接帮你从中国大学MOOC里挑选了25门 ...

  9. python大学课程-Python 爬取中国大学 MOOC 课程

    中国大学 MOOC 是网易旗下一款慕课视频教育网站.实话说,这是网易几款教育类产品中,我最喜欢的一个.自己也使用了一年多,观看视频都是需要联网的,但部分 MOOC 课程存在有效期,设定的学期结束即无法 ...

最新文章

  1. 用pandas.dataframe 的append()方法时候,合成的整个数据的索引是分块的
  2. 第四篇[机器学习] 机器学习,线性回归的优化
  3. ML之Clustering:关于Clustering进阶的那些不可告密的事
  4. mysql中00933错误_ORA-00933: SQL command not properly ended
  5. BZOJ 2456 mode
  6. PMP之项目质量管理---项目质量管理措施
  7. 单身的原因终于找到了!原来是这几个......
  8. Apache Camel中的断路器模式
  9. 总线的集中式仲裁(讲述计时器定时查询方式,独立请求方式,链式查询方式的优缺点)
  10. java兔子问题 递归_兔子问题 —— 递归的应用
  11. Kotlin定义静态变量、静态方法
  12. 为什么我离开了管理岗位
  13. pythonscipy教程_Python学习教程(Python学习路线):Python—SciPy精讲
  14. Bpmn.js 中文文档(一)
  15. 好系统U盘启动教您win7系统怎么安装其他语言
  16. 【JAVA长虹键法】第六式 原型模式(23种设计模式)
  17. 阿里云香港服务器被打流量攻击怎么办
  18. [数据分析] [保姆级教程] 数据差异分析方法
  19. 苹果市场金融类app上架ios1.2 ,5.2.1或3.21被拒原因解析
  20. termux使用教程python手机_渗透测试|利用手机攻击电脑(Termux终端初体验)

热门文章

  1. 产品学习:智能生产调度管理系统
  2. STM32实现水下四旋翼(六)传感任务2——姿态解算代码实现(使用角度传感器)
  3. 对象可以创建数组吗_企业微信活码如何创建?活码可以统计渠道来源吗?
  4. 管理人员巡店用表-店长每日工作流程
  5. 恶意软件Emotet卷土重来滥用.LNK文件进行攻击,你只需要一项技术就能有效保护组织
  6. java imageio_java-ImageIO.write()方法和png
  7. row format delimited fields terminated by ','
  8. R语言导入数据文件(数据导入、加载、读取)、使用readr包中的read_csv函数导入逗号分割文件CSV(Comma Delimited Text File)
  9. pRRophetic 通过基因表达水平预测临床化疗反应的R包
  10. cad卸载工具_CAD安装失败都是红?