乐观学习,乐观生活,才能不断前进啊!!!
我的主页:optimistic_chen
我的专栏:c语言 ,Java
欢迎大家访问~
创作不易,大佬们点赞鼓励下吧~
文章目录 抽象类什么的抽象类?抽象类语法抽象类特点 接口语法规则接口的使用接口的特点实现多个接口接口使用实例Comparable接口Clonable接口 抽象类和接口的区别Object类获取对象信息对象比较equals方法 完结 抽象类 什么的抽象类? 在Java中,所以对象都是通过类来描述的,但是反过来,并不是所有类都是用来描述对象的。如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
说明:
1.猫、狗、牛都是动物,因此和Animal类是继承关系
2.虽然动物类中也存在eat()方法,但是它不是具体的动物,没有具体的对象,因此其内部的eat()方法没有办法实现。
3.因为Animal类没有办法描述一个具体的类,所以可以将Animal类设计为“抽象类”。
主要的eat方法都是由 Animal 的各种子类的 eat 方法来完成的. 像这种没有实际工作的方法, 我们可以把它设计成一个 抽象方法(abstract method), 包含抽象方法的类我们称为 抽象类(abstract class).
抽象类语法 在Java中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
// 抽象类:被abstract修饰的类 public abstract class Animal { // 抽象方法:被abstract修饰的方法,没有方法体 abstract public void eat(); // 抽象类也是类,也可以增加普通方法和属性 public String Color(){ return black; } protected String color; // 颜色 } 抽象类特点 抽象类不能直接实例化对象
Animal animal = new Aniaml();//编译报错 //Animal是抽象的,无法实例化 抽象方法不能是private修饰
数据结构之双向链表(源码) 线性表 双向链表是线性表链式存储结构的一种,若对链式存储结构进行分类可以分为八种。
带头、不带头:指的是该连链表有无头节点,头节点不存放任何内容,它不一定是链表必备的元素,而一个链表拥有一个头节点就可以对后续的插入、删除等操作进行统一而不需要判空等情况。单向、双向:双向链表与单向链表的区别在于,它多了一个指针用来存放上一个节点的指针,这样就可以通过一个节点任意的向前、向后遍历。循环、不循环:链表的循环结构是将不循环链表的尾节点从指向空指针改为指向头指针。完成链表的自循环。 本篇所述:带头双向循环链表,简称双链表,双链表和单链表(不带头单向不循环链表)是八种链表中常用的两个链表,
双向链表 双链表结构 双链表是一个带头双向循环链表,更据它的特性不能想出,在一个双链表的一个节点里它的指针域用来存放前一个节点的地址和存放下一个节点的地址
typedef int ListNodeDataType; typedef struct ListNode { ListNodeDataType data; struct ListNode* prev; struct ListNode* next; }ListNode; prev是前驱指针存放前一个节点的地址,next是后继指针存放下一个节点的指针,而双链表是循环链表,尾节点没有下一个节点,它是指向头节点,头节点的prec指针指向尾节点。
功能实现 //初始化 void ListNodeInit2(ListNode** pphead); ListNode* LTInit(); //打印 void ListPrint(ListNode* phead); //尾插 void ListNodePushBack(ListNode* phead, ListNodeDataType x); //头插 void ListNodePushFront(ListNode* phead, ListNodeDataType x); //尾删 void ListNodePopBack(ListNode* phead); //头删 void ListNodePopFront(ListNode* phead); //查找 ListNode* ListNodeFind(ListNode* phead, ListNodeDataType x); //指定位置删除 void ListNodeErase(ListNode* pos); //指定位置插入(之后) void ListNodeInsert(ListNode* pos, ListNodeDataType x); //销毁 void ListDestory(ListNode* phead); void ListDestory2(ListNode** pphead); 创建节点、初始化、打印 创建节点 //创建节点 ListNode* ListBuyNode(ListNodeDataType x) { ListNode* newnode = (ListNode*)malloc(sizeof(ListNode)); if (newnode == NULL) { perror("
总目录:《UDS协议从入门到精通(UDS速查手册)》(完结撒花版) 一、前言一、UDS简介1.1 从汽车诊断说起1.2 两种常见的诊断协议:OBD & UDS 二、相关术语介绍2.1 Service ID(SID)2.2 诊断请求(Diagnostic Request)2.3 正响应/负响应(Positive/Negative Response)2.3.1 正响应报文格式2.3.2 负响应报文格式 2.4 负响应码(Negative Response Code - NRC) 三、UDS服务详述3.1 诊断和通信管理类3.2 数据传输类3.3 存储数据传输类3.4 IO控制类3.5 例程功能类 - 调用ECU内部预置函数3.6 上传下载类 四、写在最后 本专栏仅用于讲解UDS协议,于2024年6月24日已将所有UDS服务讲解更新完毕。博主能力有限,专栏文章中不免有疏漏之处,欢迎并感谢众多同学提出宝贵意见,博主会仔细查阅相关内容并及时修正。
另外,结合部分同学建议,后续将添加对实际工况下UDS日志的分析、UDS中对OTA相关内容的梳理、以及对UDS协议中会话层时间参数的讲解,这些文章将陆续更新在新专栏车载系统开发精品文章集锦中,欢迎关注,共同学习进步!。 一、前言 汽车软件开发/测试工作中不免涉及到UDS协议。实际上该协议的应用不仅仅局限于最常见的汽车故障检测工作中(比如4S店对汽车故障的快速定位),在车载ECU间的通信、数据传输、ECU软件的升级刷写等场景中都有着广泛的应用。
经查阅各类资料和网络文章,仔细阅读14229-1协议标准,集众多网友、博主以及自己对该协议的理解,在本专栏针对UDS 14229-1中定义的全部26种服务作详细阐述, 并以图示方式给出直观的通信示例,可以作为一部中文UDS手册,便于随手查询。
一、UDS简介 1.1 从汽车诊断说起 汽车诊断是指对汽车进行故障检测和定位的过程,它是确保汽车安全和性能的重要环节。
在汽车维修和开发工作中,诊断工具是必不可少的设备。通过诊断工具,技师可以读取车辆的故障码,进而定位故障原因。汽车软件开发或者测试人员也可以通过诊断工具连接到汽车的电子系统,读取和解析车辆的实时数据。而汽车诊断协议就是指诊断工具与车辆之间的通信协议。目前,市场上最常见的两种汽车诊断协议是OBD(On-Board Diagnostics)和UDS(Unified Diagnostic Services)。
Tip📌:诊断工具也就是下文常提到的Tester,它可以是任何实现了通信协议的东西,比如可以是一个实现了UDS协议的上位机软件、实际的硬件设备(4S店的诊断仪)甚至是一个实现了UDS协议的系统中的测试脚本。
在过去的几十年里,汽车诊断系统经历了巨大的变革和发展。起初,汽车诊断主要依靠人工检测和经验判断来发现问题。随着科技的进步,电子系统在汽车中的应用越来越广泛,汽车诊断也逐渐走向了自动化和数字化。从最初的简单故障指示灯到现在的复杂电子控制单元(ECU)和诊断协议的应用,汽车诊断技术已经取得了长足进步。
1.2 两种常见的诊断协议:OBD & UDS OBD和UDS是两种常见的诊断协议,它们在目标和应用领域上存在一些区别。OBD协议主要用于监测车辆的排放情况,通过读取车辆的故障码来判断是否符合排放标准。而UDS协议则更加全面和灵活,在各个ECU上是一种通用型的协议。
OBD(On-Board Diagnostic):
主要用于跟汽车排放系统相关的ECU(电子控制单元,汽车上的板级控制器)的诊断。OBD协议分为两种:OBD-I和OBD-II。OBD-I是由美国为当时制造的加州汽车所制定的排放法规,随后这套法规被逐渐标准化,于是又提出了OBDII标准,包括:标准化的车载ECU数据诊断接口(SAE-J1962,也就是现在常说的OBD接口)、标准化的诊断解码工具(SAE-J1978)、标准化的诊断协议(ISO 9141-2、ISO 14230-4、ISO 15765-4)、标准化的故障码定义(SAE-J2012、ISO 15031-6)、标准化的维修服务指南(SAE-J2000),OBD-II在1996年开始实施,目前已经成为全球汽车行业的标准。因此,OBD标准可以看作一系列标准的集合,是具有强制标准需要参照的,是由法规要求的,其最初目的是环保,用于汽车排放系统相关的ECU上。
UDS(Unified diagnostic services):
UDS(Unified Diagnostic Services)是一种通用的汽车诊断协议,由欧洲汽车制造商协会(ACEA)和日本汽车制造商协会(JAMA)共同制定。它与OBD最大的区别就在于“Unified“上,是面向整车所有ECU的。单就UDS而言,它只是一个应用层协议(ISO 14229-1),不关心应用层以下的实现,比如执行该协议的应用层程序不关心通过何种物理传输方式实现与ECU硬件的通信,因此它既可以基于CAN线通信去实现,也能在Ethernet上实现。并且,UDS提供的是一个诊断服务的基本框架,定义了一系列的诊断服务和通用化的诊断流程,主机厂和零部件供应商可以根据实际情况选择实现其中的一部分或是自定义出一些私有化的诊断服务来,所以基于UDS协议的诊断又常常被称为Enhanced diagnosic(增强型诊断)。可见,UDS不是法规要求的,没有统一实现标准,可以基于该协议提供的诊断请求及响应格式进行二次开发。
简言之,UDS服务主要用于诊断设备Tester(Client)和ECU(Server)之间的诊断通信,诊断设备(Tester)发送诊断请求(request),ECU给出诊断响应(response),通过这种“一问一答”的形式让目标ECU执行一些期望的操作,而UDS就是为不同类型诊断功能的request和response定义了统一的内容和格式。
参考:全景和标定全功能算法实现和exe测试demo-金书世界
1、测试环境
opencv310 vs2022 2、使用的编程语言
c和c++ 3、测试的demo的获取
更新:测试的exe程序,无需解压码就可以体验算法测试效果
百度网盘:
链接:https://pan.baidu.com/s/1OqYzPKSrsuVzmwxfPUOSXw 提取码:13z3 1、压缩包解压后显示如下所示
测试文件包括:可执行的exe文件、测试图片和视频等。
2.双击exe就可以运行测试程序,测试程序界面显示如下所示:
根据需求进行测试,以下是测试的结果视频
测试的结果视频参见:
链接:https://pan.baidu.com/s/1J4AA64Xo0SkGpCaMUF6edQ
提取码:hzk9
1、碗型任意角度
碗型任意角度
2、碗型投影
碗型
3、俯视任意角度
平面投影全景
4、俯视
俯视图
5、540度全景
AVM全景的多视图模式--540度全景
6、前视
前视
7、后视
后视
8、左前视
左前
9、右前视
右前
10、左前轮
AVM全景的车轮模式--行车左前车轮模式
11、左后轮
AVM全景的车轮模式--倒车左后车轮模式
12、右前轮
AVM全景的车轮模式--行车右前车轮模式
13、右后轮
AVM全景的车轮模式--倒车右后车轮模式
14、前视窄边
AVM全景的窄边模式--行车窄边模式
15、后视窄边
AVM全景的窄边模式--倒车窄边模式
16、标定
浅谈数学模型在UGC/AIGC游戏数值配置调参中的应用 ygluu 卢益贵
关键词:UGC、AIGC、AI智能体、大模型、数学模型、游戏数值调参、游戏策划
一、前言 在策划大大群提出《游戏工厂:AI(AIGC/ChatGPT)与流程式游戏开发》讨论之后就已完成本文的构想,现在才得以整理提出。
众所周知,无论UGC还是AIGC,都面临一个同样问题:复杂的参数调教和简单的人机交互(含AI)的矛盾。UGC毕竟他是U,没有B的强大实力,U肯定希望简单工作就能高效产出。同样,AI还不是完美的,AI也希望简单化以提升AI成品合格率,这和U的需求相吻合。
借旧图抛砖引玉:
本文将阐述以数学模型为基础提出简化数值调参的一些思路。
注:不少策划大佬讨论说属性不可能这么调,非常感谢大佬们的关注,确实是。但本文讲是思路:如何根据数据特征来抽象模型达到降维的目的,实际举例的数据有可能不成立。哪些数值是宏观调控,哪些是微观调控的是要区别去对待的,也不能一个模型通吃所有需求。
二、从音响系统的EQ调教说起 以3段EQ调频为例,提升高、中、低任意一个频点都会用数学模型来拉动相邻频点的提升,以达到频点缓和过渡的目的。
图2.1 三段EQ调频图
三、玩家等级升级经验值调参的数学模型设计 借助EQ频点提升的数学模型原理,我们可以用它来设计玩家等级升级经验值调参的数学模型。
图3.1 玩家等级升级经验值曲线图1(直线型)
根据图31,玩家等级升级经验值设置所需的维度只有4个:MinLv(最小等级)、MaxLv(最大等级)、MinUpExp(最小升级经验值)、MaxUpExp(最大升级经验值)。我们再参考EQ分段原理,引入段位维度Seg(Seq=3、5、7...),如图2.2、2.3所示:
图3.2 玩家等级升级经验值曲线图2(凹形)
图3.3 玩家等级升级经验值曲线图3(凸形)
如果经验值按10000递增话,这时再引入取整精度(Digit),如果图3.4所示:
图3.4 按取整精度获得每级升级所需经验值(200级阶梯值)
最终UGC或者AIGC调整玩家等级升级经验值所需的维度有:MinLv、MaxLv、MinUpExp、MaxUpExp、Seg、Digit,常用维度只有4个:MinLv、MaxLv、MinUpExp、MaxUpExp,次常用维度:Seg、Digit。
与传统的200级分别调整的情况相比要简单得多。
同理,玩家的攻防等属性值的调整也可以适用以上数学模型原理。具体公式就不列举了,有点数学基础的基本能实现。
四、BOSS战斗力调参的数学模型设计 我们可以借鉴图2.1,将BOSS的众多属性按攻、敏、防三类进行排序,如图4.1所示:
图4.1 BOSS战斗力调参设计
那么UGC/AIGC仅需调整BOSS的攻、敏、防三个维度的数值。
五、玩家战斗力调参的数学模型设计 玩家战斗力调参和BOSS就不一样了,BOSS是已知属性数值的,而玩家战斗力需要穿戴装备、成长线递进等才能形成最终战斗力。
图5.1 玩家战斗力调参设计
等级系统、装备系统、任务系统等各个子系统可以独立调参,当整体调参的时候也可以将所有子系统同时调参。那么UGC/AIGC调参维度远比人工要的维度要少得多。
六、数值爆表的防控 为防止数值爆表,我们可以使用图6.1所示的数学模型进行最大值防控。
图6.1 数值爆表的防控模型
七、可视化交互 无论是否进入游戏,所有被调整的数值都是无法可视化的,参考EQ的分段数学模型,UGC/AIGC调参的可视化交互界面如图7.1:
图7.1 UGC/AIGC调参的可视化交互界面
如果是UGC,用户可以直接推动五段滑杆。如果是AIGC,AI直接输出相应幅度值推动滑杆,这样AI的正确率远比直接修改200级的配置表来说高得多。
八、结束语 实际应用远比本文所述的要复杂得多,本文的示例不一定成立,但UGC/AIGC对游戏配置调参的要求不变:
1、降维:复杂事情简单做
2、抽象:抽象出数学模型或者行为模型
3、如果前2点都做不到那么是否可以整游戏的设计?(因为你面对的是你无法改变的User和AI)
图8.1 抽象高度
为什么要有链表 上一节我们描述了顺序表:【Java数据结构】初识线性表之一:顺序表-CSDN博客
并且进行了简单模拟实现。通过源码知道,ArrayList底层使用数组来存储元素。
由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。因此:java集合中又引入了LinkedList,即链表结构。
链表 链表的概念及结构
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
注意:
链表的结构在逻辑上是连续的,但是在物理位置上不一定连续。节点一般都是从堆上申请出来的。从堆上申请空间是按一定策略来分配的,两次申请的空间可能会连续,也可能不连续。 实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
单向或者双向带头或者不带头循环或者非循环 本章节我们来描述其中两种:
无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。 模拟实现无头单向非循环链表 模拟实现无头单向非循环链表主要有以下的方法:
public class SingleLinkedList {
//头插法
public void addFirst(int data){
}
//尾插法
public void addLast(int data){
}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
return false;
}
//删除第一次出现关键字为key的节点
public void remove(int key){
}
//删除所有值为key的节点
public void removeAllKey(int key){
}
//得到单链表的长度
public int size(){
return -1;
}
public void clear() {
一、编辑文件 文本编辑器有很多,比如图形模式的gedit、OpenOffice 等,文本模式下的编辑器有vi、vim(vi的增强版本)等。vi和vim是我们在Linux中最常用的编辑器。
gedit:类似于windows下的记事本,很方便的去修改文本。
OpenOffice:Linux下的office,可以进行word,excel,ppt的制作。
vim/vi:vi与vim编辑器是所有Unix及Linux系统下标准的编辑器,他就相当于windows系统中的记事本一样,它的强大不逊色于任何最新的文本编辑器。对Unix及Linux系统的任何版本,vi编辑器是完全相同的。
1.Vim的模式: 2.一般模式下的操作: x
为向后删除一个字符nx 连续向后删除n个字符
dd 删除光标所在行
ndd 删除光标所在的向下n行
yy 复制光标所在的那一行
nyy 复制光标所在的向下n列
p 将已复制的数据在光标下一行粘贴上
P
则为贴在光标的上一行
u 恢复前一个操作
3.一般模式下切换到编辑模式: i 从目前光标所在处插入
I 在目前所在行的第一个非空格符处开始插入
a 从目前光标所在的下一个字符处开始插入
A 从光标所在行的最后一个字符处开始插入
o 在目前光标所在的下一行处插入新的一行
O 为在目前光标所在处的上一行插入新的一行
r 只会取代光标所在的那一个字符一次
R 会一直取代光标所在的文字,直到按下 ESC 为止
4.一般模式切换到命令行模式: :w 保存编辑的内容
:w!
强制写入该文件,但跟你对该文件的权限有关
:q 离开vi
:q! 不想保存修改强制离开
:wq 保存后离开
:x 保存后离开保存后离开
5.vim多窗口使用技巧: 横向切割打开:
①:new+窗口名(保存后就是文件名) -->打开一个新窗口
②:split+窗口名(保存后就是文件名) -->打开一个新窗口,split可以简写为sp
纵向切割打开:
:vsplit+窗口名(保存后就是文件名) --> 打开一个新窗口, vsplit可以简写为vsp
关闭多窗口:
文章目录 全部的实现代码放在了文章末尾准备工作包含头文件定义命名空间类的成员变量为什么节点类是用struct而不是class呢?为什么要写get_head_node? 迭代器迭代器在list类里的实例化和重命名普通迭代器operator->()的作用是什么? const迭代器反向迭代器迭代器的获取 构造函数默认构造使用n个val构造迭代器区间构造解决迭代器区间构造 和 用n个val构造的冲突initializer_list构造拷贝构造 析构函数swap赋值运算符重载erase删除pos迭代器指向的节点为什么要返回next? 删除迭代器区间 insert在迭代器pos之前插入一个节点为什么要返回newnode?在迭代器pos之前插入一个迭代器区间的数据 push_backpush_frontpop_frontpop_backsizeemptybackfrontassignresizeclear全部代码 全部的实现代码放在了文章末尾 准备工作 创建两个文件,一个头文件mylist.hpp,一个源文件test.cpp
【因为模板的声明和定义不能分处于不同的文件中,所以把成员函数的声明和定义放在了同一个文件mylist.hpp中】
mylist.hpp:存放包含的头文件,命名空间的定义,成员函数和命名空间中的函数的定义
test.cpp:存放main函数,以及测试代码
包含头文件 iostream:用于输入输出
assert.h:用于使用报错函数assert
定义命名空间 在文件mylist.hpp中定义上一个命名空间mylist
把list类和它的成员函数放进命名空间封装起来,防止与包含的头文件中的函数/变量重名的冲突问题
类的成员变量 参考了stl源码中的list的实现,stl中list的底层链表是双向带头循环链表
【可以看我这篇文章了解双向带头循环链表的实现:链表的极致——带头双向循环链表】
成员变量只有一个,就是指向双向带头循环链表的头节点的指针。
节点类:
为什么节点类是用struct而不是class呢? 因为节点类里面的成员变量在实现list的时候需要经常访问,所以需要节点类的成员变量是公有的【使用友元也可以,但是比较麻烦】
struct的默认访问权限就是公有,不用加访问限定符了,stl中实现的节点类也是struct
class的默认访问权限是私有的
list类:
为什么要写get_head_node? 因为插入节点之前必须要有头节点
所以把创建初始头节点的操作写成了一个函数,用于
所有构造函数插入节点之前进行申请头节点
迭代器 因为list存储数据的方式是创建一个一个的节点存储数据
所以存储数据的空间不是连续的,所以不能直接用指针作为迭代器
因为指向一个节点的指针直接++,是不一定能指向下一个节点的
所以要把迭代器实现成一个类,这样才可以正确地支持++,- -,*等操作
迭代器在list类里的实例化和重命名 普通迭代器 template<class T, class R, class F> struct Iterator { 把自己的类型重命名一下 typedef Iterator<T, R, F> Self; 成员变量的类型是 双向带头循环链表的节点类型 listnode<T>* _n; Iterator(listnode<T>*l=nullptr) 构造函数 { _n = l; } Self& operator++()前置++ { ++就是指向下一个节点 _n = _n->_next; return *this; } Self operator++(int) 后置++ { Self tmp =*this; 先记录一下++之前的值 _n = _n->_next; 再++ return tmp; } Self& operator--() 前置-- { --就是指向上一个节点 _n = _n->_prev; return *this; } Self operator--(int) 后置-- { Self tmp = *this; 先记录一下--之前的值 _n = _n->_prev; 再-- return tmp; } R operator*()const { 类比指针 *就是获取 节点中存储的数据 return _n->_data; } F operator->()const { 返回 节点中 存储数据的成员变量的 地址 return &(_n->_data); } bool operator!
人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录
🌈个人主页:人不走空 💖系列专栏:算法专题
⏰诗词歌赋:斯是陋室,惟吾德馨
Atomic 原子类介绍
基本类型原子类
数组类型原子类
引用类型原子类
对象的属性修改类型原子类
作者其他作品:
JavaGuide官方网站:javaguide.cn
Atomic 原子类介绍 Atomic 翻译成中文是“原子”的意思。在化学上,原子是构成物质的最小单位,在化学反应中不可分割。在编程中,Atomic 指的是一个操作具有原子性,即该操作不可分割、不可中断。即使在多个线程同时执行时,该操作要么全部执行完成,要么不执行,不会被其他线程看到部分完成的状态。
原子类简单来说就是具有原子性操作特征的类。
java.util.concurrent.atomic 包中的 Atomic 原子类提供了一种线程安全的方式来操作单个变量。
Atomic 类依赖于 CAS(Compare-And-Swap,比较并交换)乐观锁来保证其方法的原子性,而不需要使用传统的锁机制(如 synchronized 块或 ReentrantLock)。
这篇文章我们只介绍 Atomic 原子类的概念,具体实现原理可以阅读笔者写的这篇文章:什么是乐观锁和悲观锁?Java 中 CAS 是如何实现的?。
JUC原子类概览
根据操作的数据类型,可以将 JUC 包中的原子类分为 4 类:
1、基本类型
使用原子的方式更新基本类型
AtomicInteger:整型原子类
AtomicLong:长整型原子类
AtomicBoolean:布尔型原子类
2、数组类型
使用原子的方式更新数组里的某个元素
AtomicIntegerArray:整型数组原子类
AtomicLongArray:长整型数组原子类
AtomicReferenceArray:引用类型数组原子类
3、引用类型
AtomicReference:引用类型原子类
AtomicMarkableReference:原子更新带有标记的引用类型。该类将 boolean 标记与引用关联起来,也可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
🐛 修正(参见:issue#626:https://github.
Jupyter 是一个开源项目,旨在为研究人员、数据科学家、教育工作者和软件开发者提供一个交互式计算平台。它最初由 Fernando Pérez 开发,现在已经成为数据科学和科学计算领域最受欢迎的工具之一。本文将介绍 Jupyter 的核心概念、特性以及如何使用 Jupyter 进行交互式数据分析和可视化。
Jupyter 简介 Jupyter(原名 IPython Notebook)是一个交互式计算环境,支持超过 40 种编程语言,包括 Python、R、Julia 和 Scala。Jupyter 的核心是一个 Web 应用程序,允许用户创建和共享包含实时代码、计算、可视化和叙述性文本的文档。
Jupyter 的核心特性 交互式计算:在 Web 浏览器中直接运行代码并查看结果。多语言支持:支持多种编程语言,通过内核(Kernel)实现。丰富的文档:文档可以包含 Markdown 文本、LaTeX 数学公式和 HTML 内容。易于分享:通过 Jupyter Notebook 文件(.ipynb)分享完整的分析过程和结果。协作编辑:支持多人同时编辑和运行 Notebook。集成工具:与 Git 等版本控制系统和 Docker 容器技术无缝集成。 使用 Jupyter 安装 Jupyter Jupyter 可以通过 Anaconda 或 pip 安装。推荐使用 Anaconda,因为它提供了一个完整的科学计算环境。
使用 Anaconda 安装:
conda install jupyter 使用 pip 安装:
pip install notebook 启动 Jupyter Notebook 在终端或命令提示符中运行以下命令启动 Jupyter Notebook 服务器:
查了很多资料,也夹杂着一些自己的见解。此篇文章仅探讨三个问题:物联网与通信技术的关系;5G为物联网带来了什么,物联网真的需要5G吗;物联网发展的现实问题。
1、物联网与通信技术的关系 最近几年,物联网的概念非常火,和物联网相关的技术,例如NB-IoT、LoRa、eMTC等,都频繁地出现在我们的身边,出现在网络上,出现在各种科技展会上。
为什么需要物联网?那就要说到通信了,他俩之间的联系,可谓千丝万缕。
通信的历史,和人类史一样漫长。可以说,没有它,就没有人类社会。人类诞生之日起,就有了通信,从烽火台,到驿站,再到无线电报,固定电话,手机,WiFi等,都是通信技术。
近几十年来,通信技术的主要奋斗目标,就是把每一个人连接起来。现在,至少在我们国家,在欧美一些发达国家,基本上都已经做到了“人均一部手机”,有钱的甚至有好几部手机。可以说,人连接人的世界已经存在了。那接下来,通信技术又该往哪发展呢?
世界的连接远不止人与人之间的通信,这个世界,除了人,还有物,一些本就存在的物,一些人类因需求而发明的物。人连接的目的是为了信息传递,资源共享,那物呢?政治上我们都学过“物质资料的生产方式是社会存在和发展的物质基础”。人类要发展,必须有更高效的生产方式。
通信工具也是工具,借助强大的通信网络,可以无限扩大人类的控制边界。人类能控制的已经不再是眼前的物体,而是遥远的物体,或者庞大的系统。例如一个城市级的系统,甚至是一个国家级的系统。
物联网,就是这样的工具,帮助你连接和控制万物。
我们来设想一下,如果可以控制能想到的任何物体,我们会做些什么?
我可以远程集中管理公共基础设施,同时进行环境监测,例如对路灯、井盖的监控(监管和控制),这样能大大降低成本,提升效率。我还可以设计研发智能手环,给女士们使用,监控身体健康的各项指标。我甚至可以开一个无人船运公司,随时随地为用户提供远洋物流服务。
没有想不到,也没有做不到。物联网的背后是一个全新的世界。有场景,就有需求;有需求,就有市场;有市场,就有了发展的方向和动力。这是物联网背后蕴藏的巨大价值与潜力。
其实,“物联网”并不是一个新鲜词,20年前就有这样的叫法。
1990年,就出现了第一台物联网设备——施乐公司9的网络可乐贩售机;
1995年,比尔盖茨在《未来之路》一书中也曾提及物联网,他描述了这样一个场景:“人们可以佩戴一个电子饰针与房子相连,电子饰针会告诉你房子你是谁你在哪,房子将用这些信息尽量满足你的需求。当你沿着大厅走路时,前面的光会渐渐变强,身后的光会渐渐消失,音乐也会随着你一起移动。”;
1999年,麻省理工学院9(MIT)的Kevin Ash-ton教授首次提出物联网的定义……
迄今为止,二三十年都过去了。人们一直都在谈论物联网,一直在宣扬它的价值,但是,它也一直处于“叫好不叫座”的境地。
为什么呢?
不是因为需求不足,也不是因为资金不够,而是因为技术没有成熟。
过去,我们所说的物联网,是基于无线局域网(WLAN)技术的物联网。物联网终端°,接入的是无线路由器°或专门的网关设备。你家的摄像头、门窗传感器、智能灯,只能连接Wi-Fi,通过Wi-Fi进行控制,就和家里的PC电脑一样。
Wi-Fi物联网虽然方便,但是太耗电了。所以慢慢有了Zigbee,有了蓝牙(Bluetooth)。但是,功耗依然很高,电池依然不够用。而且,它们的传送距离太短了。例如蓝牙,你房子稍微大一点,就没有信号了,连接中断。WLAN物联网,家庭使用需求都无法满足,更别说工业企业那种大型应用场景了
所以,WLAN物联网一直未能被市场所接受。
现在,以NB-IoT、LoRa为代表的LPWAN物联网技术崛起了。LPWAN (Low-Power Wide-Area Network,低功耗广域网)物联网技术,彻底解决了WLAN物联网的问题。
以NB-loT为例,它的优点如下:
广覆盖,增益高,覆盖面积大,信号质量好,网络建设成本低!省钱!
低功耗,一个电池用10年,摆脱了对电源和电线的依赖。彻底的无“线”!又是省钱!大连接,决定了它支持海量的终端,一个小区就能hold住几万个点!
低成本,每个通讯模块才几十块钱(将来甚至几块钱),价格便宜!
成本是决定一项技术能否投入应用的一项关键指标。而目前,像NB-IoT这样的技术,既拥有良好的性能参数,又拥有市场可以接受的低成本,已经具备了成熟应用的条件。
所以说,现在的物联网还真不是“噱头”,万物互联的时代,真的到来了。
2、5G为物联网带来了什么,物联网真的需要5G吗? 有人说:现在的物联网和5G关联都是为了蹭热度。只有5G环境才能运营的物联网模式不存在。目前所有的物联网模式都是可以在2g,3g,4g下运行,而且很好。那为什么还需要5G呢?
也有人说:万物互联不需要5G,反而5G的覆盖范围是致命缺陷。万物互联并不需要很大的带宽,只需要足够的接入点而已。物联网的核心是动态库存管理、调度,通信干路上永远都是光纤,到终端才转换成5G信号,所以5G会比光纤更快吗?哪怕库存物品不联网,照样可以实现。
所以说,5G究竟为物联网带来了什么,物联网真的不需要5G吗?
你有没有想过,为什么一直到了5G才提出万物互连呢?之前在4G的时候不行吗?其实并不是,5G与物联网其实真的没有什么必然联系。哪怕你是2G,理论上也是可以接入互联网的。之所以5G才能真正实现万物互连其实有一个很重要的因素就是“延迟”。举个例子,在医用物联网,著名的外科医生需要远程操纵电子手术刀对患者进行手术,如果手术刀因为延迟的原因偏离几毫米或者错过最佳时间,可能就会给患者带来难以估量的严重后果,这时候,就需要更低的网络传输延迟满足这一要求。在5G以前,此类情况是很难克服的。
5G的三大应用场景(eMBB、mMTC、uRLLC),其中有两大,是物联网场景。
eMBB:增强型移动宽带, (Enhance Mobile Broadband),人与人之间通信,人类上网,主要用这个。
mMTC:海量物联网通信,(Massive Machine Type Communication),物联网主要用这个。
uRLLC:低时延、高可靠通信,(Ultra Reliable & Low Latency Communication)主要用于智能无人驾驶、工业自动化等需要低时延高可靠连接的业务。
需求带来场景,场景带来产品,颠覆性的产品,才能形成市场,才能拯救行业。现在,能够拯救通信行业的,也不会是5G,而是物联网,还有它背后的需求。所以,准确来说,是物联网需求召唤5G技术,5G技术支撑物联网需求。
如果没有需求的支撑,以5G那么惊人的投资成本,是不可能有所作为的。
在我看来,无人驾驶,虚拟现实,智慧城市,工业4.0,这些才是5G存在的意义
总而言之,盲目追求技术指标9和参数,寄希望于5G靠技术性能拯救行业,是不现实的。物联网领域的应用场景挖掘,以及物联网应用的用户体验,才是真正需要关注的重点。物联网,主要还是基于5G的速度和价格。到了人人都用流量而价格适中,就会呈现出大规模的物联网应用场景。
所以,5G的出现能够更好的支持物联网的实现,使得物联网广泛大面积的应用成为了可能。正是网络通信技术的不断革新,使得过去的二十年,互联网将人与人连在一起。但也是基于此,今后的二十年,互联网会将一切连在一起。
3、物联网发展的现实问题 以上两点,我只说了,物联网多么的好,5G多么的厉害,却没有揭露它发展背后的现实。
各国对物联网都积极支持,在看似百花齐放的背后,能够真正投入并大规模使用的物联网项目少之又少。因为在成本没有达到普遍可以接受的范围内,物联网的发展只能是空谈。又受限于技术上的瓶颈,物联网的发展,其实无法像当初互联网那样爆发。或者换通俗一点的说法,大家有没有发现,很多物联网的应用,其实是锦上添花的东西,需求性并没有那么强,这也就是为什么很多智能硬件卖得并不是很好的根本原因;正是因为需求性原因,所以商业上也不会出现滴滴打车那样的持续性投入,又一定程度上钳制了技术的进一步发展。
同时,在管理层面来说,物联网自身就是一个复杂的网络体系,加之应用领域遍及各行各业,不可避免的存在很大的交叉性。如果这个网络体系没有一个专门的综合平台对信息进行分类管理,就会出现大量信息冗余、重复工作、重复建设造成资源浪费的状况。每个行业的应用各自独立,成本高、效率低,体现不出物联网的优势,势必会影响物联网的推广。所以,物联网现急需要一个能整合各行业资源的统一管理平台,使其能形成一个完整的产业链模式。
不仅如此,最要关心的还是信息安全问题。5G使物联网的连接节点变得更多,增加了网络安全攻击和黑客攻击的风险。从应用的角度来看,物联网上传着大量有关企业金融、生产、物流、销售数据的信息资源,我们保护这些数据的安全比保护显示屏上显示的游戏数据更重要的多、困难的多。
但是,有困难,就一定会有解决办法,几百年前,谁能想得到人类能登上月球、火星啊。物联网得发展前景是复杂的,但也是广阔的,挑战越多,突破口就越多,很多技术还值得我们继续研究,继续创新。
总之,物联网到底能发展成什么样,时间终会告诉我们。
写在前面:
栈和队列是两种重要的线性结构。其也属于线性表,只是操作受限,本节主要讨论的是栈和队列的定义、表示方法以及C语言实现。
一、栈和队列的定义与特点 栈:是限定仅在表尾进行插入和删除的线性表。对栈来说,表尾有着特殊的含义,称为栈顶,表头称为栈底,不含元素的空表称为空栈;
栈的特点就是:按后进先出的原则进行的,栈又称为后进先出的线性表;
与栈相反的是队列,队列是一种先进先出的特点。它只允许在标的一段进行插入,在另一端进行删除。允许插入的一段称为队尾,允许删除的一段称为队头。
二、栈 2.1顺序栈 顺序栈是指利用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放在自栈底到栈顶的数据元素。
设指针top指向栈顶元素在顺序表中的位置,base指针指向栈底元素在顺序栈中的位置。
2.1.1初始化 typedef struct Node { int *base; int *top; int stacksize; }Node; //初始化栈 void InitStack(Node *S) { S->base = (int *)malloc(sizeof(int)*MAXSIZE); S->top = S->base ; } 初始化,创建一个结构体类型,其中变量为栈顶指针、栈底指针,以及栈的最大空间;
使栈顶和栈底都指向空间的基地址;
2.1.2入栈 int PushStack(Node* S,int data) { if (S->top - S->base == MAXSIZE) { return -1; } else { *(S->top) = data; (S->top)++; } } 判断栈是否满,不满将新元素压入栈顶,栈顶指针+1; 2.1.3出栈 int PopStack(Node * S) { if (S->top == S->base) return -1; else { (S->top)--; int i = *(S->top); return i; } } 判断栈顶是否为空,若不为空,栈顶指针减1,栈顶元素出栈; 2.
问题描述 已知有三个坐标点:P0、P1、P2,当满足P3和P4连成的一条直线 与 P0和P1连成一条直线平行且长度一致,该如何计算P3、P4?
解决办法 思路一:斜率及点斜式方程 # 示例坐标 x0, y0 = 1, 1 # P0坐标 x1, y1 = 4, 4 # P1坐标 x2, y2 = 2, 2 # P2坐标 # 计算直线P0P1的斜率 m = (y1 - y0) / (x1 - x0) # 设定P3和P4在x轴上的不同值 x3 = x2 - 1 x4 = x2 + 1 # 使用点斜式方程求P3和P4的y坐标 y3 = m * (x3 - x2) + y2 y4 = m * (x4 - x2) + y2 # P3和P4的坐标 P3 = (x3, y3) P4 = (x4, y4) P3, P4 思路二:斜率及两线相交 直线的斜率 斜率是数学中的一个概念,特别是在解析几何和平面直角坐标系中,用来描述一条直线倾斜程度的量。它定义为直线上任意两点之间的垂直变化量(即纵坐标的变化量,通常称为“上升”或“Δy”)与水平变化量(即横坐标的变化量,通常称为“运行”或“Δx”)之比。斜率通常用字母 m 表示。
RPA鼠标按键使用技巧 Mouse.MouseAuto.Action命令出错,调用的目标发生了异常,Exception in Mouse.Action元素不可用怎么解决
出现问题 1.想要实现的效果鼠标移动到录屏工具的小球上 2.点击开始按钮开始录屏 现象,鼠标没有移动痕迹,但是调试信息输出点击小球成功,点击开始按钮,提示调用目标异常,元素不可用。定位到源码如下 Mouse.Action(@ui"窗口_EVCapture7","left","click",10000,{"bContinueOnError": false, "iDelayAfter": 300, "iDelayBefore": 200, "bSetForeground": true, "sCursorPosition": "Center", "iCursorOffsetX": 0, "iCursorOffsetY": 0, "sKeyModifiers": [],"sSimulate": "simulate", "bMoveSmoothly": false}) 在官网上查阅到各参数的意义:
解决方法 初学者看到鼠标平滑移动更能清楚的观察是哪里出现了错误,将最后一个参数改为True :
修改之后发现鼠标并未点击到小球上,而是停留在中间区域,如下
代码参数中,有一个描述光标起点名可以,默认选择的是center
选中的目标并不是一个小球,而是包括小球在内的较大的矩形区域,点击其中心点,必然弹不出开始、停止、编辑等按钮。
将参数Center 改为 TopLeft ,在将光标进行适量偏移在x轴上偏移30,在y轴上偏移30,就可以点击到小球,出现开始,停止,编辑等选项了。随后在点击开始按钮,就不会出现目标异常的问题了
1. 微信小程序图片保存功能概述 1.1 功能需求与重要性 微信小程序图片保存到手机相册的功能对于用户而言具有较高的实用价值。用户在浏览小程序时,可能会遇到希望保存的图片内容,如商品图片、活动海报、个人照片等。这一功能使得用户能够方便地将这些图片保存到手机中,以便日后查看或分享。
用户体验:提供图片保存功能可以提升用户对小程序的满意度,增加用户粘性,尤其是在电商、社交媒体等场景中,用户对图片的保存需求尤为突出。营销推广:对于商家而言,用户保存的图片可能成为传播的媒介,有助于品牌的推广和营销活动。 1.2 微信小程序API支持情况 微信小程序提供了wx.saveImageToPhotosAlbum API,允许开发者实现图片保存到手机相册的功能。然而,这一API的使用需要用户授权,且不支持直接保存网络图片路径,需要先下载图片到本地。
API限制:wx.saveImageToPhotosAlbum API的使用受到一定的限制,例如必须在用户主动触发的情况下调用,且需要用户授权写入相册的权限。实现步骤:通常的实现步骤包括检查用户是否已经授权、请求用户授权、下载图片到本地、调用API保存图片等。 技术实现与用户授权
2.1 技术实现流程 实现微信小程序图片保存功能需要开发者遵循一定的技术流程,包括但不限于:
权限检查:使用wx.getSetting或wx.authorize检查并请求用户授权。图片下载:使用wx.downloadFile将网络图片下载到本地,获取临时文件路径。保存图片:调用wx.saveImageToPhotosAlbum并传入本地图片路径,实现图片保存。 2.2 用户授权机制 用户授权是实现图片保存功能的关键步骤,需要用户明确同意小程序保存图片到手机相册。
首次授权:在用户首次使用保存功能时,小程序需要通过wx.authorize或wx.getSetting检查用户是否已经授权。引导授权:若用户未授权,小程序需要引导用户前往设置页面手动授权,或通过弹窗等方式提示用户授权。 实际应用案例分析
3.1 电商小程序中的应用 在电商小程序中,用户常常需要保存商品图片进行分享或比对。通过实现图片保存功能,可以提升用户体验,增加商品的曝光率。
案例分析:以某知名电商平台的小程序为例,用户在浏览商品详情时,可以通过点击“保存图片”按钮,将商品图片保存到手机相册中。 3.2 社交媒体小程序中的应用 社交媒体小程序中,用户生成的内容(UGC)如个人照片、活动照片等,常常需要保存和分享。图片保存功能为用户提供了便利。
案例分析:以某社交平台的小程序为例,用户在查看好友分享的照片时,可以选择将喜欢的照片保存到手机中,以便日后查看或进一步分享。 用户体验与隐私保护
4.1 用户体验优化 在实现图片保存功能时,开发者需要考虑用户体验的优化,包括操作的便捷性、提示信息的友好性等。
交互设计:设计直观的界面和操作流程,使用户能够轻松理解和使用图片保存功能。反馈机制:在用户操作过程中,提供清晰的反馈信息,如保存成功提示、操作失败的提示等。 4.2 隐私保护措施 图片保存功能涉及到用户数据的处理,开发者需要重视用户隐私保护,合理处理用户数据。
数据安全:确保下载和保存的图片数据安全,防止未经授权的访问和泄露。用户知情:在请求用户授权时,明确告知用户图片保存的目的和使用范围,保障用户的知情权和选择权。 2. 用户授权流程 2.1 获取授权的API使用 微信小程序在保存图片到手机相册时,首先需要用户授权。这一过程可以通过wx.getSetting()和wx.authorize()两个API来实现。
wx.getSetting()用于获取用户当前的授权状态,包括是否已经授权了scope.writePhotosAlbum权限。此API的使用可以避免重复请求用户授权,提升用户体验。wx.authorize({scope: 'scope.writePhotosAlbum'})用于请求用户授权。如果用户首次打开小程序,或者之前未授权过,此时会弹出授权窗口请求用户确认。 使用示例: wx.getSetting({ success: (res) => { if (!res.authSetting['scope.writePhotosAlbum']) { // 用户未授权,需要请求授权 wx.authorize({ scope: 'scope.writePhotosAlbum', success: () => { // 用户已授权,可以进行保存图片操作 }, fail: () => { // 用户拒绝授权,需要引导用户去设置页面手动授权 wx.
使用 Transformer 解码器(Transformer decoder)生成 tokens 需要以下两个步骤。这两个步骤分别是处理提示语步骤和多个自回归步骤。两个步骤在硬件利用上有着截然不同的特征。 程序员 - LLM 推理优化探微 (4) :模型性能瓶颈分类及优化策略 - IDP技术干货 - SegmentFault 思否
1.LLM 做出回答的两个阶段 文本生成的两个阶段包括:启动阶段和生成阶段。
Transformer 解码器的模型轮廓图:
解码器本身并不输出 tokens,而是输出 logits(数量与词汇表的大小相同)(译者注:logits 是一个数值向量,其维度等于词汇表的大小,表示每个 token 的可能性分数。)在生成文本时,通过 logits 提取 tokens 的过程是通过一种被称为搜索策略(search strategy)、生成策略(generation strategy)或解码策略(decoding strategy)的启发式方法完成的。
基于 Transformer 的解码器从输入文本序列(通常称为提示语(prompt))生成文本(通常也被称为对输入文本的扩展或补充)基本上包括以下步骤:
将模型权重加载到GPU在CPU上对提示词(prompt)进行分词(tokenizing),并将token张量传输到GPU。 分词步骤示意图:
将分词完成后的提示语输入神经网络,生成扩展的第一个token 这一阶段通常被称为启动阶段(initiation phase)。 在下一篇文章中,我们将看到它也经常被称为预填充阶段(pre-fill phase)。
将生成token附加到输入的token序列中,并将其用作生成扩展文本中第二个token的新输入。然后,重复此过程,直到生成了停止序列或达到所配置的最大序列长度。 这个由多个步骤组成的阶段通常被称为生成阶段(generation phase)、解码阶段(decoding phase)、自回归阶段(auto-regressive phase),甚至是增量阶段(incremental phase)。
将完成的 tokens 从 GPU 获取到 CPU ,并对它们进行 detokenize(译者注:”detokenize“指的是将模型生成的 tokens 序列转换回原始文本或句子的过程。可能包括去除 tokens 之间的空格、添加标点符号、还原缩写等操作,以还原生成文本的自然语言形式。),以获取生成的文本(图5)。 论在硬件上如何进行计算,两个阶段之间确实没有区别,因此两个阶段在这方面都没有什么特别之处。这种设置涉及大量冗余计算,因此在许多情况下效率低下。缓解这种情况的一种重要方式是缓存我们不想重新计算的内容。这种优化被称为 KV 缓存,并引入了我一直在暗示的这两个阶段之间的关键差异。
单头注意力 :
假设只处理长度为 t 的单个输入序列,则会有 t 个查询向量、t 个键向量和 t 个值向量。对于每个查询向量,都会生成一个输出向量,输出向量是输入序列中所有值向量的线性组合,每个值向量在线性组合中的权重由对应的注意力分数决定。换句话说,对于每个查询向量,生成的输出向量是通过对输入序列中的值向量进行加权求和而得到的,其中权重由注意力分数确定。对于给定的查询向量,都会与所有的键向量进行点积运算。点积运算的结果表示了查询向量与每个键向量之间的关联度,即它们的相似性。这些点积的结果经过适当的处理后,成为了注意力分数,用于权衡对应值向量在输出向量中的贡献。这样,我们就能为序列中的每个 token 生成一个包含其他 token 信息的向量表征,也就是说,我们为每个 token 创建了一个上下文表征(contextual representation)。
C-有大家喜欢的零食吗_河南萌新联赛2024第(一)场:河南农业大学 (nowcoder.com) 思路:匈牙利算法的板子题. 二部图
int n; vector<int> vct[505]; int match[505],vis[505]; bool dfs(int s){ for(auto v:vct[s]){ if(vis[v]) continue; vis[v]=1; if(!match[v]||dfs(match[v])){ 女生没有伴侣,或者其伴侣可以选择其他女生 match[v]=s; 糖果v被s孩子选了 return 1; } } return 0; } 有大家喜欢的零食吗 https://ac.nowcoder.com/acm/contest/86639/C void solve(){ C 匈牙利🇭🇺--求最大匹配 cin>>n; for(int i=1;i<=n;i++){ int k; cin>>k; for(int j=1;j<=k;j++){ 孩子选糖果 int x; cin>>x; vct[i].emplace_back(x); } } int ans=0; for(int i=1;i<=n;i++){ if(dfs(i)) ans++; for(int j=1;j<=n;j++) vis[j]=0; init } if(ans==n) cout<<"Yes"; else cout<<"No"<<endl<<n-ans; } B-爱探险的朵拉_河南萌新联赛2024第(一)场:河南农业大学 (nowcoder.com) 思路:拓扑脱点之后,处理每一个环,环里的每一个点的可达大小都可以处理出来,并且同一个环中的点的可达大小都是一样的。处理完之后,再dfs处理环外的点,环外的点只要遇到!dis[x]==1的点就可以停止了.
目录
1.概述
1.1. 对话系统(Chat)
1.2. 自主代理(Agent)
1.3. 小结
2.整体介绍
2.1.对话系统(Chat)
2.1.1.发展现状
2.1.2.主要技术
2.1.3.应用场景
2.2.自主代理(Agent)
2.2.1.发展现状
2.2.2.主要技术
2.2.3.应用场景
2.3.小结
3.技术对比
3.1. 技术差异
3.2. 优势和劣势
3.3. 技术挑战
3.4.小结
4.未来展望
4.1.Chat AI的发展趋势
4.2.Agent AI的发展趋势
4.3.社会和经济影响
4.4.小结
1.概述 生成式AI的未来发展方向是一个复杂而多元的话题,涵盖了技术、伦理和实用性的各个层面。目前看来,对话系统(Chat)与自主代理(Agent)都是发展的重要方向,并且二者的发展并非彼此独立,而是相辅相成。
1.1. 对话系统(Chat) 对话系统的主要优势在于其与人类的直接交互能力,可以在多种场景下提供信息支持、咨询服务等。通过提高自然语言处理的质量,生成式AI可以更好地理解和回应用户的需要,从而在教育、医疗、客服等行业中扮演更加重要的角色。对话系统的发展也提出了对AI模型的透明度、可解释性和伦理问题的更高要求。 1.2. 自主代理(Agent) 自主代理强调的是AI的自主决策和执行任务的能力,包括但不限于机器人技术、自动驾驶、智能制造等领域。通过与物理世界的交互,自主代理能够扩展AI的工作范围,从而解放人力资源,提高生产效率和安全性。这一方向的挑战在于如何确保AI的决策符合道德规范和法律法规,以及如何有效地管理AI与人类的关系和界限。 1.3. 小结 生成式AI的未来似乎不会单纯偏向任何一个方向,而是在多个方向上相互促进、并行发展。科技企业、研究机构和政府部门在推动AI技术进步的同时,也需要关注相应的法规制定、伦理准则建立,以及公众的知情权和参与权保障。全方位协调发展将更可能推动生成式AI技术走向成熟,更好地服务于社会和人类。
2.整体介绍 生成式AI在对话系统和自主代理两个领域已取得显著进展,不仅推动了人工智能的边界,也改变了多个行业的运作方式。下面详细介绍这两个领域的发展现状、主要技术和应用场景。
2.1.对话系统(Chat) 2.1.1.发展现状 对话系统,特别是生成式对话系统,已经从简单的基于规则的响应系统演化为更加复杂和智能的系统,能够生成连贯且相关性强的回答。通过使用深度学习,尤其是转换器(Transformer)模型,现代对话系统能够理解并生成自然语言,提供更加人性化和有吸引力的交互体验。
2.1.2.主要技术 Transformer 模型:用于大量NLP任务的核心架构,如BERT、GPT系列等。上下文理解:通过长期记忆网络,例如LSTM,以及注意力机制,系统能够处理并记住用户的历史交谈,从而提供更加个性化的回答。自然语言理解(NLU)和生成(NLG):使系统能够理解用户的输入并生成自然流畅的回答。 2.1.3.应用场景 客服机器人:在电商、银行、旅游等行业为用户提供问题解答和信息查询。个人助手:如智能手机和智能家居设备中的助手,帮助用户执行任务、设定提醒和搜集信息。娱乐和社交:在游戏和社交平台中与用户进行互动。 2.2.自主代理(Agent) 2.2.1.发展现状 自主代理指的是可以在没有人类直接干预的情况下自动执行任务的AI系统。利用AI技术独立作出决策,并完成复杂的任务序列,广泛应用于机器人、自动化服务和复杂决策支持系统中。
2.2.2.主要技术 强化学习:通过与环境的交互,代理学习如何在给定任务中最大化其奖励。多智能体系统:使多个代理能够在同一环境中协作或竞争,常用于模拟和战略游戏。决策树和路径规划:用于执行特定任务,比如导航和物流优化。 2.2.3.应用场景 自动驾驶车辆:使用AI进行环境感知、决策制定和路径规划。无人机调度:在农业、救灾和物流领域进行自主飞行和任务执行。智能建筑管理:自动控制建筑内的照明、温度和安全系统。 2.3.小结 生成式AI在对话系统和自主代理领域的持续发展正在推动这些技术从理论研究走向日常应用,极大地增强了业务操作的效率和用户的交互体验。随着技术的不断进步,未来这些系统将变得更加智能和自适应,能够处理更加复杂的任务和场景。
3.技术对比 生成式AI在Chat和Agent两个方面的应用展现了AI技术的广泛性与深度。以下是对这两个方向上的技术差异、优势、劣势以及面临的技术挑战的探讨。
3.1. 技术差异 Chat (聊天系统):
本章内容包括
创建、启动和停止pod使用标签组织pod和其他资源使用特定标签对所有pod执行操作使用命名空间将多个pod分到不重叠的组中调度pod到指定类型的工作节点 pod是kubernetes中最为重要的核心概念,其他对象仅仅为管理、暴露pod或被pod使用。
1 pod是什么 pod是一组并置的容器,代表了kubernetes中最基本构建模块。在实际应用中不会单独部署容器,更多的是针对一组pod的容器进行部署和操作。但这并不意味这一个pod要包含多个容器,kubernetes以pod为基本单位,所以即使一个pod中包含了多个容器,但这多个容器实际上是运行在一个node中。
1.1 为什么需要pod 为什么kubernetes需要pod?而不是直接使用容器?为什么需要同时运行多个容器?不能把所有进程都放在一个容器里面嘛?
1.1.1 为什么运行多个容器? 容器被设计为每个容器只运行一个进程(除非进程本身产生子进程),这样能保证容器和服务具有相同的生命周期,这样才能最好的应用容器编排来管理好容器和服务。如果一个容器内运行多个不相干的进程,那么kubernetes将无法很好的管理这些进程。设计每个容器只允许一个进程有以下好处:
简化管理和伸缩:每个容器只运行一个应用程序,使得水平伸缩变得容易。当需要更多资源时,可以快速创建新的容器,而无需担心多个应用程序之间的相互影响。提高服用性:单个容器只运行一个应用程序,可以方便地将容器重新用于其他项目或目的,从而提高容器的复用性。简化故障排查:当容器出现故障时,开发人员可以专注于排查特定应用程序的问题,而无需对整个系统的各个部分进行排查。这有助于提高容器的可移植性和可预测性。提高应用持续生命周期管理的灵活性:升级程序时,可以将影响范围控制在更小的粒度。这有助于避免在升级某个服务时中断相同容器中的其他进程。提高安全性和隔离性:每个容器只运行一个应用程序,有助于提供更安全的服务和应用程序间的隔离。这有助于保持强大的安全状态,或遵守PCI之类的规定。 1.2 了解pod 由于不能将多个进程聚集在一个单独的容器中,所以需要一种更高级的结构来将容器绑定在一起,并将它们作为一个单元进行管理,这就是请问什么需要pod的原因。
在包含容器的pod下,我们可以同时运行一些具有超亲密度的进程,并为它们提供相同的环境。此时这些进程就好像全部运行在单个容器中一样,同时又保持着一定的隔离。这样一来就能全面利用容器所提供的特性,同时对这些进程来说它们就像运行在一个机器上一样。
1.2.1 同一pod中的部分隔离 容器与容器之间是完全隔离的,但当一组容器具有超亲密度关系的时候,我们会期望它们之间是部分隔离,而不是完全隔离。也就是隔离容器组,让每个容器组内的容器共享一些资源,而不是全部。kubernetes使用pod来使一组容器共享相同的命名空间。如以下几个命名空间:
UTSIPCNET
新版的kubernetes也支持共享PID命名空间,但并不是默认开启的,可以通过设置pod的shareProcessNamespace的值为true来开启这个功能。 但当涉及到文件系统时,情况就变的有点不一样了。因为容器的文件系统来自容器镜像,因此在默认情况下,每个容器的文件系统与其他容器完全隔离,所以需要使用kubenetes中的volumn资源来共享文件目录。
1.2.2 pod网络 由于一个pod中的容器运行于相同的Network空间,所以一个pod中的容器共享相同的IP和端口端口空间,所以在同一个pod中运行的多个进程注意别绑定到相同的端口。
kubernetes集群中所有的pod都在同一个共享网络地址空间中,所以每个pod都可以通过其他pod的IP地址来实现相互访问。同一个集群下的pod通信是没有net(网络地址转换)的。这是通过网络插件实现的,所以不同的网络插件有不同的实现方式,但目的都是为了给pod提供一个统一的网络环境,使pod可以直接通信。
1.3 通过pod合理管理容器 由于pod比较轻量,可以让我们在几乎没有任何额外开销的情况下拥有尽可能多的pod,所以我们应该将应用持续组织到多个pod中,每个pod只保存具有超亲密度关系的容器。
1.3.1 将多层应用分散到多个pod中 在云原生架构中,我们应该尽可能的把不同的组件放到不同的pod中,并且把pod调度到不同的工作节点中,这样才能最大的利用不同节点的计算资源,提高基础架构的利用率。
另一个将不同组件放到不同pod上的考虑是kubernetes的扩缩容是基于pod的,如果将多个组件放到同一个pod中,那么扩缩容时也将把多个组件同时进行,所以当一个组件有单独扩缩容的需求时,应该把它放到一个单独的pod中。
1.3.2 何时在pod中使用多个容器 一般将具有超亲密度关系的容器放在一个pod中,例如,部署一个web应用和其日志收集器,这个时候就需要把这两个容器放在一个pod中。这也是kubernetes中常用的边车模式(siedecar)。
当需要决定多个容器是否需要存放在一个pod中时,可以根据以下问题决定:
它们需要一起运行还是可以运行在不同的主机上?它们代表的时一个整体还是相互独立的组件?它们必须一起扩缩容还是可以分别进行? 基本上,除了具有超亲密度的容器,一般倾向于在单独的pod中运行单独的容器。
2 用YAML创建pod pod和其他kubernetes资源通常时通过向kubernetes REST API提供JSON或YAML描述文件来创建的。一般来说,pod的yaml文件会包含以下几个部分:
apiVersion:YAMl描述文件所使用的Kubernetes API版本kind:kubernetes对象资源类型metadata:pod元数据,包括名称、标签、注解、命名空间等spec:pod规格/内容说明,包括pod的容器列表、volume等status:只读的运行时数据,pod及其内部容器的详细状态,如pod所处的条件,每个容器的描述和状态,以及内部IP和其他基本信息。一般创建时不需要指定 # kubia-manual.yaml apiVersion: v1 # 使用v1版本的API kind: Pod # 描述一个pod metadata: name: kubia-manual # 名字为kubia-manual spec: containers: # pod容器列表 - image: luksa/kubia # 镜像的名称 name: kubia # 容器的名称 ports: # 应用监听端口 - containerPort: 8080 protocol: TCP 在pod定义中指定端口纯粹是展示性的(informational)。忽略它们对于客户端是否可以通过端口连接到pod不会带来任何影响。但明确定义端口任然是有意义的,在端口定义下,每个使用集群的人都可以快速查看每个pod对外暴露的端口,还可以为每个端口定义一个名称,方便我们使用。
1.目标
使用数据集绘制柱状图和折线图,
使用时间序列数据构建历史平移特征和窗口统计特征,
使用lightgbm模型进行训练并预测。
2.
特征工程,作为机器学习项目中的核心环节之一,不仅深刻影响着模型性能的优劣,更是区分顶尖参赛者与普通参赛者的关键所在。它不仅仅是对现有数据的简单处理或转换,而是一门艺术与科学的结合,要求从业者具备深厚的领域知识、敏锐的洞察力和创新的思维方式。
数据与特征的重要性 “数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限。”这句话深刻地揭示了特征工程在机器学习中的核心地位。数据的质量、丰富度以及特征的有效性直接决定了模型能够学习到的信息量和复杂度,从而限定了模型性能的理论极限。即使是最先进的算法,如果缺乏高质量的特征支撑,也难以发挥出其应有的潜力。相反,通过精心的特征设计,即便是相对简单的模型,也能在特定问题上取得令人瞩目的效果。
特征工程的步骤 数据探索与理解:这是特征工程的起点,通过统计描述、可视化等手段,深入理解数据的分布、缺失情况、异常值等,为后续的特征选择和转换奠定基础。
特征选择:从原始特征集中筛选出对预测目标最有价值的特征。这可以通过相关性分析、卡方检验、互信息等方法实现,旨在减少模型的复杂度,提高训练效率和泛化能力。
特征构造:基于领域知识和对数据的深入理解,通过数学变换、组合、聚合等方式,创造出新的、更富表达力的特征。这一过程往往依赖于对业务逻辑的深刻理解和对数据内在关系的敏锐洞察。
特征缩放与标准化:为了确保不同量纲和分布的特征在模型中能够公平比较,需要对特征进行缩放或标准化处理。这有助于提升模型的收敛速度和稳定性。
特征编码:对于分类特征,需要通过独热编码、标签编码等方式进行数值化,以便模型能够处理。
特征工程的创新 在机器学习竞赛中,特征工程的创新往往成为获胜的关键。参赛者不仅需要运用现有的特征工程技巧,还需要结合具体问题的特点,创造性地设计出新的特征。这种创新可能来源于对业务逻辑的深入理解,也可能来自于对数据内在规律的独到发现。
总之,特征工程是机器学习项目中不可或缺的一环,它要求从业者既要有扎实的理论基础,又要有丰富的实践经验;既要能深入理解业务逻辑,又要能敏锐捕捉数据中的微妙变化。通过不断地探索和实践,我们可以在特征工程这条道路上越走越远,为机器学习模型性能的提升贡献更多的力量。
3.机器学习项目主要步骤的详细扩写
在利用机器学习模型解决实际问题的过程中,遵循一系列系统而有序的步骤是至关重要的。这些步骤不仅帮助确保项目的顺利进行,还能有效提升模型的性能和可靠性。以下是对主要步骤的详细扩写:
1. 探索性数据分析(Exploratory Data Analysis, EDA) 探索性数据分析是机器学习项目的起点,它涉及对原始数据的深入探索和可视化。在这一阶段,数据分析师或数据科学家会运用统计方法和可视化工具(如直方图、散点图、箱线图等)来揭示数据的分布、趋势、异常值以及变量之间的关系。EDA的目标是增进对数据集的理解,为后续的数据预处理和特征工程提供指导。
2. 数据预处理(Data Preprocessing) 数据预处理是机器学习项目中至关重要的一步,它直接影响到模型的性能。预处理工作包括但不限于数据清洗(如处理缺失值、异常值)、数据转换(如编码分类变量、缩放数值变量)、数据集成(合并多个数据源)以及数据规约(减少数据集的维度或样本量)。通过这些步骤,可以确保输入到模型中的数据是干净、一致且适合分析的。
3. 特征提取与工程(Feature Extraction & Engineering) 特征提取与工程是构建有效机器学习模型的关键。在这一阶段,需要根据业务需求和问题特点,从原始数据中提取出对预测目标有影响的特征。这可能需要结合领域知识、数据探索的结果以及实验性的尝试。特征工程还包括对特征的进一步处理,如特征选择(减少冗余特征)、特征构造(创造新特征)和特征变换(如PCA降维、多项式特征等),以增强模型的学习能力。
4. 切分训练集与验证集(Splitting into Training and Validation Sets) 为了评估模型的性能并防止过拟合,需要将数据集切分为训练集和验证集(有时还包括测试集)。训练集用于训练模型,而验证集则用于调整模型参数和评估模型性能。通过交叉验证等技术,可以进一步提高模型评估的准确性和稳定性。
5. 训练模型(Model Training) 在准备好数据并选择了合适的机器学习算法后,就可以开始训练模型了。训练过程涉及使用训练集数据来优化模型的参数,使模型能够准确预测目标变量。训练过程中需要监控模型的性能指标,如准确率、召回率、F1分数等,以评估模型的性能。
6. 预测与评估(Prediction & Evaluation) 完成模型训练后,就可以使用验证集或测试集来评估模型的性能了。评估过程包括使用模型对未见过的数据进行预测,并计算性能指标以衡量模型的准确性、泛化能力等。根据评估结果,可以对模型进行进一步的调整和优化。
4. GBDT GBDT (Gradient Boosting Decision Tree) 是机器学习中一个长盛不衰的模型,其主要思想是利用弱分类器(决策树)迭代训练以得到最优模型,该模型具有训练效果好、不易过拟合等优点。
GBDT不仅在工业界应用广泛,通常被用于多分类、点击率预测、搜索排序等任务;在各种数据挖掘竞赛中也是致命武器,据统计Kaggle上的比赛有一半以上的冠军方案都是基于GBDT。
LightGBM LightGBM(Light Gradient Boosting Machine)是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以快速处理海量数据等优点。
LightGBM 框架中还包括随机森林和逻辑回归等模型。通常应用于二分类、多分类和排序等场景。
例如:在个性化商品推荐场景中,通常需要做点击预估模型。使用用户过往的行为(点击、曝光未点击、购买等)作为训练数据,来预测用户点击或购买的概率。根据用户行为和用户属性提取一些特征,包括: