Category: ICT-Information and Communication Technology

  • 深度学习框架中自动微分的实现

    自动微分的实现为深度学习的框架的梯度回传的计算提供了很大的便捷,我们只需定义好算子(operator),搭建好整个深度神经网络的网络结构后,就可以通过拓扑序构建好(具体拓扑排序方法可以参考引文中的深度优先搜索方法DFS)计算图,然后就可以根据偏微分的链式法则,就可以依次反向计算节点的数值结果,参数梯度等数值了。 在不同的深度学习的框架中,神经网络反向传播的算法实现会存在着一些差异,以早期的比较有影响力的caffe举例说明,caffe的实现中没有算子,而是blob(tensor)和layer,Net三种粒度的结构,各种不同的计算方法的layer(类似于各种不同的operator,如加减乘除)中计算前向和反向的结果,layer的输入为bottom blob,输出为top blob(也有可能存在着inplace的操作)其计算流图的关系是通过Net类中的相关函数进行静态计算的(Init函数)。 深度学习框架经过技术的发展,早期的caffe已经淡出了研发者的视线,不过在当时(还没有出现tensorflow,caffe2,以及pytorch)是相当有影响力的,其中的设计思想也是比较优秀的,有兴趣的读者可以阅读某些layer的forward,backward函数(基于cpu和gpu(cublas库)的矩阵计算)的实现都可以具体阅读源码加以具体深入的理解。不过由于其python的接口支持不是特别丰富,一些特殊的层的自定义实现和框架的重编译门槛比较高,相比pytorch要繁琐很多。 现在基于pytorch的深度学习框架由于其简洁易用而广受欢迎,其网络的定义也更加自由灵活(代码定义网络结构也很方便),基于pytorch的深度学习应用框架也有很多,纷繁多样,比如openmmlab等等。 Reference

  • WordPress本地备份重部署方法

    WordPress作为最有名的开源博客系统之一,由于其便捷的部署方式和丰富的样式和插件,使得其在个人博客,中小型内容管理系统(CMS,content management system)中广受欢迎。这篇博客将记录部署和维护wordpress的一些细节方法和技巧,后续有更多的会继续在文章后面进行补充。 1、部署,docker技术可以使得部署wordpress系统非常便捷,wordpress基本依赖两个docker镜像,mysql和wordpress。部署方式可以通过下面的两个脚本命令启动相关容器进行。在公有云如阿里华为上部署时一般还要配置nginx的conf,购买SSL证书并进行签名部署等操作,一般公有云上也会有相关文档说明,这里不做特别说明。 2、备份,这里用比较笨拙的全量备份到本地并进行本地部署的方式进行介绍。环境为windows10/11和WSL的ubuntu18.04。1、首先通过scp将在服务器上的mysql目录和wordpress的目录全量拷贝到本地。2、拉取两个docker镜像,wordpress和mysql:5.7。3、启动对应的两个docker容器,启动方式为上述的启动脚本示例。 3、进入mysql容器内部(docker exec -it containerid bash),登录到sql服务器(mysql -uroot -ppassword),选择数据库(use databasename),通过sql指令更新本地定义的域名。 4、配置SSL和本地域名解析。具体方法为:1、在WSL的ubuntu环境中生成本地ssl证书,2、检查WSL中的ip;3、在windows原生系统中添加一行本地域名解析(C:\Windows\System32\drivers\etc目录下的hosts文件),格式为:wsl ip:new_domain。其中前两点的CLI(command line interface)命令如下: 5、在WSL中安装配置nginx,conf的配置方法和云平台中的配置方法类似,阿里云华为云上也有相关的配置说明,这里不做赘述。配置好后,通过命令nginx -s reload更新配置属性。然后就可以在windows系统的浏览器的状态栏中输入https://new_domain就可以访问备份的博客系统了。 References

  • Windows系统上安装配置docker环境

    Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。 docker的应用场景挺多,比如一般的AI云平台都是基于docker镜像提供的系统环境,一般的软件开发也会基于docker软件编译和运行环境(如apollo系统的编译运行环境就是基于docker的)。 docker是对于开发者非常友好的工具,从个人经验来看,在docker环境下做开发和部署有如下的好处和便捷:1、docker镜像的开发环境和机器原生系统隔离,机器本身的软件环境不受影响;2、不同的开发环境比如依赖库等可以构建不同的docker镜像来进行隔离(有点类似于anaconda的虚拟环境);3、镜像一次构建后很容易分发共享,如通过docker hub进行push和pull就可以推送本地镜像和远程拉取所需的镜像。这样的镜像机制也同时方便团队合作以及系统生产环境的部署。 在linux系统如ubuntu或其他发行版本上使用docker相对比较容易,而我们平时用windows机器的场景也挺多,本文将记录在windows平台上构建docker开发环境的方法。 1、首先在windows10/11上安装WSL(windows subsystem for linux)环境,由底层虚拟机平台所支持,因此需要开启相关服务。方法为:在桌面底部的搜索栏输入“控制面板”后选择程序-》启用或关闭windows功能后勾选两项:1、适用于Linux的Windows子系统;2、虚拟机平台;3、开启虚拟机服务平台,执行此命令行后继续进行相关的操作。dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart和wsl –set-default-version 2。中间可能需要重启系统以更新相关服务。 2、在桌面底部状态栏中输入“store”选择Windows Store中搜索ubuntu 18.04。然后选择下载,下载完成后即可运行。 3、下载docker desktop for windows程序并安装后既可以通过启动图标来启动docker engine。然后就可以在windows上的Ubuntu系统里使用docker命令了。 Reference

  • 几个基本的线代知识点

    这篇文章简要介绍一下线性代数的相关概念知识,如行列式,特征值,特征向量以及特征值分解,SVD分解等。在这里顺便记录一下以便后续查阅。 1、行列式(determinant),矩阵对应一个特定的值,一般记为det(A),余子式(minor)m_{i,j}一般记为当前矩阵去除i行j列后形成的行列式(由此也可以理解为行列式为递归定义),代数余子式(cofactor)需要在m_{i,j}的基础上再乘上一个因子(-1)^{i+j}形成c_{i,j}。同时有伴随矩阵(adjoint matrix)的概念也是基于代数余子式进行定义的。需要注意,行列式只针对于方阵。 基于伴随矩阵就比较容易计算矩阵的逆。如下所示,也可以看出矩阵的逆要求其行列式不为0。 2、特征值特征向量(也是方阵,对于非方阵来说,是不存在特征值的,但是会存在条件数):满足特征方程(characteristic equatation)det(A-lamda I)=0的lambda的值即为矩阵的特征值。实对称矩阵的特征向量相互正交。特征值有其对应的代数重数(Algebraic multiplicity),每个特征值有其对应的几何重数(Geometric multiplicity,即为其对应的线性无关的特征向量的个数)。缺陷特征值(defective eigenvalue)指的是存在这个特征值的几何重数比代数重数要小的特征值。关于代数重数大于等于几何重数的相关证明,可以参考引文的链接。 3、特征值分解和SVD分解,可以参考引文3和引文4,其中特征值分解满足方阵,实对称矩阵的特征向量线性无关且为相互正交,PCA就用到了这个特性,SVD分解可以解决不是方阵的情况,但是可以通过转化为特征值分解的方法去进行求解,具体的方法可以参考引文3。特征值的计算方法可以用QR分解来进行。 References

  • 交互式VR在视觉增强方面可能的应用

    人类个人的感知,认知和创造性都是有限制的,这里仅从视觉感知增强的方面来说一说元宇宙相关技术的作用。所描述的场景和应用只是一些可能的案例,实际上会有更多丰富的场景,但也有待去更好的在技术产品上落地实现,在实际中得以很好的应用。 人类在感知上存在着较大局限,比如仅从视觉上来讲,人的眼睛只能感受波长较窄的一段可见光,看不清微观世界运行的细节,也看不清大的宏观宇宙的全貌,人的视角也很有限制,不能同时看到360度周视全貌,以及遮挡视线部分的内容。感知是认知的基础,人类首先能够看得见听得着,才能不断积累对世界的认识并代代相传,智慧才能不断升级。 人类感知能力的局限可以由现在科技的发展进行拓展和增强,人们越来越会制造高级的工具来延申我们的视觉感知,听觉感知以及行动力等等。就拿VR来说,可以应用的场景很多,特别在小的微观细节和大的宏观全貌的交互式可视化上将能够大有所为。这里就简要的来说一说。 比如生物化学这些领域,一些分子结构的交互动态可视化,DNA双螺旋到底长成什么样子,一些生物医药,特别对于生物学和医学的同学,如果能够通过VR技术来可视化很多生物微观的细节结构和动态行为,那这里的学习和理解将更加的直观和深刻。 再比如大的宏观结构,数字孪生地球,太阳系和银河系等等,都是非常有教育价值的场景,通过数字地球,未来我们甚至可以随时云上游览地球的任何一个地方,我们可以通过缩放来了解地月的运行方式,太阳系的行星和卫星,以及可能的太阳系带着自己的行星卫星和星云在银河系中飞奔的场景。 还有很多的场景可以用到,如展示栩栩如生的已经灭绝的古生物,中小学语文课历史课等内容都可以制作设计精良的交互可视化内容。以后VR,AR和AI相结合的元宇宙产品,有更多的内容期待着大家发挥神奇的想象力,期待后面这些方面也能有所实践。

  • Apollo 粗粒度结构及系统启动流程简介

    Apollo系统是智能驾驶领域很有影响力的开源系统,本篇文章从粗粒度上介绍Apollo系统的结构,并分析其其启动流程。后续有机会再介绍细节,不正确的地方欢迎批评指正。 Apollo系统是个比较复杂的系统应用,首先其实现了通信及任务调度的中间件CyberRT(在代码仓的apollo\cyber目录下),也称为Apollo系统的运行时环境(RT即为Runtime),Apollo系统的各个业务逻辑模块,包括感知perception,规划planning,控制control等等各上层的模块,都是基于CyberRT的基础上进行构建的。CyberRT提供了两个核心的运行时功能,1为任务调度,基于协程,多线程实现的不同任务可以按照智能驾驶的业务逻辑编排成高效的执行模式运行,2为通信模式,借鉴了ROS里边的node发布订阅模式,实现了进程内(intra),shm(共享内存单机多进程间通信),rtsp(实时发布订阅协议,多个host之间的网络通信协议),以及hybrid(混合模式,基于component之间通信的物理状态动态选择上述三种模式以达高效通信)。在CyberRT的实现里,一个任务以component为载体,里边的业务处理逻辑通过协程来实现,同时其有对应node,实现了reader和writer,也就是可以接收和发送消息(不同的消息以channel来区分,类似于ros里的topic)。关于通信的实现可以参考apollo\cyber\transport目录下面的代码,引文2中也有相关的介绍。 CyberRT可以理解为在底层操作系统之上构建的一个RTOS,在Apollo的源码仓里,系统的各个模块的逻辑实现依赖于CyberRT提供的接口,这些模块的代码在目录apollo\modules里。具体阅读相关代码实现。 这里以一个模块的启动为例进行说明,一般来说,每一个模块都有一个启动的文件(dag有向无环图文件),如下面的路径为摄像头bev感知模块的dag文件:apollo\modules\perception\camera_detection_bev\dag\camera_detection_bev.dag。一般通过mainboard程序启动一个module。mainboard即为cyberrt运行时编译后生成的可执行文件,会加载CyberRT运行时环境,load相应模块的so文件(一个module可以由多个component组成)。而整个新系统将会是很多个module组成的大系统,因此会有很多个mainboard程序启动,整个智能驾驶系统将是一个多进程程序(不同进程有可能会跨不同的主机host)。具体的启动方式的介绍在引文3中有详细介绍,在此不做赘述。 References

  • Apollo CyberRT的两种任务调度策略实现代码简要说明

    Apollo CyberRT为智能驾驶的中间件(middle ware),提供了类似于ROS概念(并优于ROS平台)的机器人运行时环境。CyberRT在任务的调度上进行了优化的设计,提供了经典调度模式和编排调度模式,使得系统的诸多任务可以按照任务之间的逻辑拓扑结构来进行编排,从而在执行性能上得到很好的保证。同时CyberRT在通信上也做了很好的支持,在单机内部,多机之间的不同component都能够进行高效的通信。这里主要就任务调度方式来做一下说明,也是加以记录以备后面查阅,不正确的地方欢迎批评指正。 首先,在CyberRT实现里,Processor类对应着线程的封装,CRoutine类是对协程的封装,Component类对应着组件(任务)的封装,在Component类里,会创建协程来处理任务。 经典调度模式(ClassicContext):在经典调度模式下,可以将任务进行分组,分组的目的主要是在基于NUMA架构的计算环境上,实现资源的隔离,在同一个组的任务会安排在同一个NUMA节点下运行,这样保证了同一组的任务之间的通信不会由于跨NUMA节点而带来更多的资源消耗和计算时长。而且每一个组下面维护一个多优先级的协程(CRoutine)队列,每一个优先级下面维护一个协程的数组。ClassicContext类对经典调度模式的上下文进行了建模,而且在CyberRT实现里,每一个Processor对应着一个ClassicContext,并且任务(component,以协程的方式实现)的优先级队列作为ClassicContext类成员的静态变量,在不同的线程里边实现共享。ClassicContext调度任务时,会从高优先级的任务里优先调度。在这里补充说明一下,CRoutine的同一个实例可以在不同的线程里调度,CRoutine类里有thread_local类型的相关变量,保证了同一个协程在不同的线程里有对应的相关变量的副本。 编排调度模式(ChoreographyContext):在编排调度模式下,一个Processor对应着一个ChoreographyContext,并且封装了一个multimap类型的变量,key为协程的优先级,value为协程,保证了可以支持同等的优先级下的多个协程。而且这个变量不是静态变量,在多个线程(Processor)之间不共享,保证了执行的协程任务的CPU亲和性(不会在多个cpu之间调度同一个协程),可以基于此通过配置文件来实现任务的编排(如定义某些任务在某些cpu上执行)。 更多的代码细节建议阅读官方开源的代码仓的关键部分,如apollo\cyber\scheduler,apollo\cyber\croutine,apollo\cyber\component等,上述的文字说明都可以在这几个目录的代码里找到实现。 References

  • QR分解及用其求矩阵特征值方法简介

    QR分解是一种特殊的矩阵分解,将矩阵A(m,n)分解为标准正交矩阵Q(m,n)和上三角矩阵R(n,n)的乘积,QR分解可以用来求矩阵的特征值等应用。 首先解释一下施密特正交化的方法,施密特正交化将n个线性无关的向量转化为标准正交向量,其转化的步骤是首选选一个向量,然后在计算第二个向量时,将原始的第二个向量可以分解为第一个向量和垂直于第一个向量的两个向量的和。而可以利用在同一个方向上的两个向量的内积之比值即为两个向量长度的比值等特性求出第二个向量(和第一个向量垂直),以此同样的类似方法求得第三个向量,第四个向量等等。从而得出施密特正交法的公式。具体公式可以参考引文。 经过施密特正交化的方法可以得出n个标准正交的列向量,而且原始的每一个列向量都可以表示为这n个标准正交列向量的线性组合,根据施密特正交向量的生成特点,原始的列向量的线性组合的线性因子刚好符合上三角矩阵的形式。 第二种算法为Householder transformation,其依次利用列向量和标准正交基形成镜像对称的特征去找到变换的Q的关系,得出Q的特性(对称正交),具体算法请参考引文链接。 QR分解的一个用处就是用来计算矩阵的特征值,具体的原理不做特别说明,如有兴趣可以参考引文链接。下图说明了怎么用numpy基于QR分解去计算矩阵的特征值。 References

  • A*算法简介以二维数字魔方为例

    A*算法又称为启发式搜索算法,是在可能的解空间中,以更少的时间或步骤去找到路径问题答案的一种方法。用到A star算法的场景挺多,如路径规划,二维数字魔方,三维立体颜色魔方(生活中常见的魔方)等等,都可以用A*算法来加快搜索的进度。也是算法基础课中最典型的一个算法,一般要求去用代码实现,并且和原始的穷举式路径搜索,启发式函数的搜索结果(可能有多种不同的启发式函数方法)进行对比。 这里以一个二维数字魔方游戏为例来进行说明,二维数字魔方为一个9宫格,每个格子一个数字,每一个当前的状态可以用一个数字串来描述,数字串的顺序为9宫格从上到下从左到右的顺序进行依次排列而成,0代表空的格子,其邻居的格子可以移动到0这个位置,移动后相当于进行了互换。如“608435127”这个串就代表了一个二维数字魔方的状态,我们一般定义目标状态为“123456780”。要求为从当前状态通过移动方格去达到目标状态。 我们对这个问题进行建模如下,1、状态建模,可以用3*3的二维数组来表示当前状态和目标状态;并且用(x0,y0)表示空的格子(数字0的格子)的坐标,用移动的操作方向来记录移动的操作路径(D表示向下,U表示向上,L表示向左,R表示向右);2、用g cost代表当前已经搜索到达的路径所需花销,用h cost代表从当前状态到达目标状态预估的(heuristic)的开销,总花销f cost为g cost + h cost。 具体的搜索算法有基于Dijkstra最短路径搜素算法,它从起点开始搜索时,总是优先搜索和展开当前离起点路径最短的节点,直至搜索到目标点时结束搜索。A*算法正是以“优先搜索直觉上方向靠谱的节点”为策略来减少搜索空间达到加速搜索目标点的目的。具体从代码实现上来解释即为:(1)、Dijkstra最短路径搜索算法将上述的g cost的大小作为路径展开的优先级;(2)、A*算法则用g cost + h cost的大小作为路径展开的优先级,使得搜索路径尽可能朝着目标状态的方向去展开。 以上述的二维数字魔方为例进行说明,Dijkstra最短路径搜索算法维护一个优先级队列,存放已经遍历的节点(路径)的代价函数g cost(以最小堆min heap的形式),然后每做一次搜索,就会从堆顶pop出节点并对其successors进行核查,如果没有遍历过,则将其g cost设为当前的g cost+1并push到优先级队列中;这个过程持续直至pop出的节点即为目标节点。 A*算法和Dijkstra最短路径搜索算法大体搜索流程差不多,不同的地方在于代价函数,A*算法的代价函数为g_cost+h_cost,其中g_cost和上述的Dijkstra算法相同,关键在于h_cost的设计,基于此特定问题,有两种特殊的h_cost函数,1为曼哈顿距离(每个魔方方块的位置和其目标位置的横坐标和纵坐标的距离之和),2为魔方单元块和其目标位置不对应的单元块个数。关于启发式函数的特性和设计准则,可以参考引文链接。 我们针对上述的几个搜索算法在借鉴了已有工作和相关思路的基础上提供了完整的代码实现,具体可以参考引文链接。 References

  • 虚实结合的生活工作空间设想

    随着元宇宙、人工智能和5G,6G区块链等技术的进步和融合,未来我们的生活工作方式将会有较大的变化,新的数字化时代科技发展日新月异,超乎我们的想象,这里就先天马行空的来说一说未来可能的情况和场景。 以IT公司为例,未来程序员编程实现工作将更多的由程序员的数字代理来完成,现实生活中的程序员可以负责来review和优化代码,以及程序的集成等工作。 家庭生活空间也类似,这里每个人可以由实体成员,实体机器人代理和虚拟代理三个角色构成,实体机器人负责在家庭物理空间完成一定的任务,如家务购物等,虚拟代理可以参加虚实融合的教学家长会,完成一些实体成员日程生活的记录如记账网购等活动。甚至我们日常活动中产生的想法和行动都可以数字化到元宇宙空间中,虚拟代理和实体在认知状态和行为上实现同步。某种意义上这样的数字虚拟代理可以实现实体个人成长经历一定程度的永久化,后代们将会更加具体的看到前人的生活工作情况,是一个活生生的家庭族谱,可以设置时间分辨率去浏览回顾,个人或伴侣也可以在年迈的时候去回忆曾经的美好时光。 综合上面两个场景及可能的更多的常见来看,未来虚拟空间将展现越来越重要的作用,虚拟空间将拥有更强大的生产力,人们的日常工作将会越来越多的由我们在虚拟空间的代理来完成,每一个组织,包括最小单位的个人,到家庭,公司,政府单位等都可以在元宇宙空间中建立虚拟代理,这些代理还可以在元宇宙空间中互联,实现更大的社交元宇宙,就像我们的物理世界中组织模式一样。也有说元宇宙就是下一代互联网,不过其组成元素将大大扩展很多,将是一个和现实世界平行发展但也有耦合和交互的虚拟世界,理想状态甚至是和物理世界同步运行着的一个镜像世界,或者加入非物理世界的人为构造和想象的部分,以及可能的多个不同特色和任务的虚拟世界,相互耦合着相互影响着推动整体世界向前运行。