首页 文章 精选 留言 我的

精选列表

搜索[可视化工具],共10011篇文章
优秀的个人博客,低调大师

可视化大屏 + AI 智能体

作为研发人员,我们每天面对的不是概念和愿景,而是接口、延迟、数据一致性和系统稳定性。最近“大屏+AI智能体”的热度很高,老板们希望在屏幕上加个对话框,仿佛就能解决所有决策问题。但真正落地时,挑战远比想象中复杂。本文从研发工程师的视角,聊聊我们在实际项目中遇到的技术难点、踩过的坑,以及一些务实的解决思路。

优秀的个人博客,低调大师

反向传播算法:定义,概念,可视化

定义 向前传播 通常,当我们使用神经网络时,我们输入某个向量x,然后网络产生一个输出y,这个输入向量通过每一层隐含层,直到输出层。这个方向的流动叫做正向传播。 在训练阶段,输入最后可以计算出一个代价标量J(θ)。 反向传播算法 然后,代价通过反向算法返回到网络中,调整权重并计算梯度。未完待续…… 分析 可能是你们在学校里做过用代数的方法来分析反向传播。对于普通函数,这很简单。但当解析法很困难时,我们通常尝试数值微分。 数值微分 由于代数操作很困难,在数值方法中,我们通常使用计算量大的方法,因此经常需要用到计算机。一般有两种方法,一种是利用近邻点,另一种是利用曲线拟合。 随机梯度下降法 负责“学习”的算法。它使用了由反向传播算法产生的梯度。 反向传播算法 然后,反向传播算法返回到网络中,调整权重来计算梯度。一般来说,反向传播算法不仅仅适用于多层感知器。它是一个通用的数值微分算法,可以用来找到任何函数的导数,只要给定函数是可微的。 该算法最重要的特点之一是,它使用了一个相对简单和廉价的程序来计算微分,提高效率。 如何计算一个代价函数的梯度 给定一个函数f,我们想要找到梯度: x是一组我们需要它的导数的变量,y是额外的变量,我们不需要它的导数。 为了使网络继续学习,我们想要找到代价函数的梯度。 损失函数 这个函数通常应用于一个数据点,寻找预测点和实际点之间的距离。大多数情况下,这是距离的平方损失。 代价函数 这个函数是所有损失函数的组合,它不总是一个和。但有时是平均值或加权平均值。例如: 如何计算一个代价函数的梯度 给定一个函数f,我们想要找到梯度: x是一组我们需要它的导数的变量,y是额外的变量,我们不需要它的导数。 为了网络的学习,我们想要找到代价函数的梯度。 微积分链式法则 假设x是实数,f和g都是实数到实数的映射函数。此外, 根据链式法则, 多变量链式法则 已知x和y是不同维数的向量, g和f也是从一个维度映射到另一个维度的函数, 或者说, ∂y /∂x是g的n×m雅可比矩阵。 梯度 而导数或微分是沿一个轴的变化率。梯度是一个函数沿多个轴的斜率矢量。 雅可比矩阵 有时我们需要找出输入和输出都是向量的函数的所有偏导数。包含所有这些偏导数的矩阵就是雅可比矩阵。 有函数 雅可比矩阵J为: 张量的链式法则 我们大部分时间都在处理高维数据,例如图像和视频。所以我们需要将链式法则扩展到张量。 想象一个三维张量, z值对这个张量的梯度是, 对于这个张量, iᵗʰ 指数给出一个向量, 所以考虑到这一点, 张量的链式法则是, 概念 计算图 这是一个关于直线方程的计算图的例子。开始节点是你将在方程中看到的,为了计算图的方便,总是需要为中间节点定义额外的变量,在这个例子中是节点u。节点“u”等价于“mx”。 我们引入这个概念来说明复杂的计算流程的支撑算法。 还记得之前,当我们把损失函数定义为差的平方,这就是我们在计算图的最后一层使用的。其中y是实际值a是预测值。 请注意,我们的损失值严重依赖于最后的激活值,而最后的激活值又依赖于前一个激活值,再依赖于前一个激活值,以此类推。 在神经网络的前进过程中,我们最终得到一个预测值a。在训练阶段,我们有一个额外的信息,这就是网络应该得到的实际结果,y。我们的损失函数就是这些值之间的距离。当我们想要最小化这个距离时,我们首先要更新最后一层的权重。但这最后一层依赖于它的前一层,因此我们更新它们。所以从这个意义上说,我们是在向后传递神经网络并更新每一层。 敏感性改变 当x的一个小变化导致函数f的一个大变化时,我们说函数对x非常敏感如果x的一个小变化导致f的一个小变化,我们说它不是很敏感。 例如,一种药物的有效性可用f来衡量,而x是所使用的剂量。灵敏度表示为: 为了进一步扩展,我们假设现在的函数是多变量的。 函数f可以对每个输入有不同的敏感度。举个例子,也许仅仅进行数量分析是不够的,所以我们把药物分解成3种活性成分,然后考虑每种成分的剂量。 最后一点扩展,如果其中一个输入值,比如x也依赖于它自己的输入。我们可以用链式法则来找出敏感性。同样的例子,也许x被分解成它在身体里的组成部分,所以我们也要考虑这个。 我们考虑x的组成,以及它的成分如何影响药物的整体效果。 在这里,我们测量的是整个药物的效果对药物中这个小成分的敏感度。 一个简单的模型 这个计算图考虑了节点a和它前面的节点a '之间的连接。 用链式法则, 它测量了a对u的微小变化有多敏感。然后我们继续前面的3次计算, 测量u对以下每一项的微小变化的敏感度: 权重,w 之前的激活值,a ' 偏质,b 把这些放在一起, 简单模型的复杂性 如果在前面的例子中,我们有两个节点和它们之间的一个链接。在这个例子中,我们有3个节点和2个链接。 因为链式法则的链式长度是没有限制的。我们可以对任意数量的层继续这样做。对于这一层,注意计算图是这样的, 请注意,需要用附加的刻度对每个节点进行注释。这些刻度不是衍生物,它们只是表示u和u '是不同的、唯一的值或对象 复杂模型的复杂性 到目前为止的例子都是线性的,链表式的神经网络。把它扩展到现实的网络是这样的, 我们需要给网络添加一些额外的符号。 让我们通过 a¹₁计算一下计算图 a²₁。 实际上你会发现两个计算图有一个很大的共同点,特别是到a¹₁。这意味着,如果一个计算已经被计算过,那么它可以在下一次和下下次被重用,依此类推。虽然这增加了内存的占用,但它显著减少了计算时间,而且对于大型神经网络来说,这是必要的。 如果我们用链式法则,得到的公式几乎是一样的,只是增加了索引。 复杂模型的进一步复杂化 你会发现一个a²₂ 会有几个路径输出层节点,。 所以我们需要对前一层求和。我们从所有前面的节点和它们的梯度的总和中得到的这个值有更新它的指令,以便我们最小化损失。 最小化成本函数 如果你还记得定义6和7,特别是定义7,你会记得成本函数在概念上是预测产出和实际产出之差的平均值或加权平均值。 如果我们使用线性回归或逻辑回归的梯度下降算法来最小化代价函数。 对于神经网络,我们使用反向传播算法。我想现在已经很清楚为什么我们不能对神经网络使用单一方程了。神经网络并不是我们可以很好地求导数的连续函数。相反,它们近似一个函数的离散节点。因此需要一个递归算法来找到它的导数或梯度,这需要考虑到所有的节点。 完整的成本函数是这样的: 从概念上讲 符号对符号导数 到目前为止,您已经了解了如何得到神经网络中节点梯度的代数表达式。通过链式法则在张量上的应用和计算图的概念。 代数表达式或计算图不处理具体问题,而只是给我们的理论背景,以验证我们正在正确地计算它们。它们帮助指导我们的编码。 在下一个概念中,我们将讨论符号对数值导数的影响。 符号-数值导数 这里我们开始脱离理论,进入实践领域。 算法 基本设置+计算节点的梯度 首先我们要做一些设置,包括神经网络的顺序以及与网络相关的节点的计算图。我们把它们排列好。 每个节点u^{(n)} 都与一个操作f^{(i)}相关联,使得: 在𝔸^ {(i)}是所有节点的集合,u^ {(n)}的父节点。 首先我们需要计算所有的输入节点,为此我们需要将所有的训练数据以x向量的形式输入: for i = 1, ...., n_i u_i = get_u(x_i) 注意,n_i为输入节点数,其中输入节点为: 如果这些是输入节点,则节点: 是输入节点之后最后一个节点之前的节点u^{(n)}。 for i = n_i+1, ..., n A_i = { u_j = get_j(Pa(u_i)) } u_i = fi(A_i) 你会注意到,这和我们链式法则计算图的概念上的方向是相反的。这是因为这部分详细说明了正向传播。 我们称这个图为: 利用这个图,我们可以构造另一个图: G中的每个节点计算正向图节点u^i,而B中的每个节点使用链式法则计算梯度。 如果你考虑神经网络中的所有节点和连接它们的边,你就能想到反向传播所需的计算量随着边的数量线性增加。因为每条边都代表了一条链规则的计算,它将一些节点连接到它的一个父节点。 附加约束+简单的反向传播 如前所述,该算法的计算复杂度与网络的边数呈线性关系。但这是假设求每条边的偏导数需要一个常数时间。 在这里,我们的目标是建立一个具体反向传播算法。 Run forward propagation 这将获得处于随机的或非有用状态的网络的激活值。 Initialize grad_table 在这个数据结构中,我们将存储所有我们计算的梯度。 To get an individual entry, we use grad_table(u_i) 这将存储计算值: grad_table[u_n] = 1 这将最后一个节点设置为1。 for j = n-1 to 1 grad_table[u_j] = \\sum grad_table[u_i] du_i/du_j 理论上是这样的: return grad_table 反向传播算法只访问每个节点一次来计算偏置,这避免了不必要的重新计算子表达式的步骤。请记住,这是以更多内存占用为代价的。 作者:Tojo Batsuuri deephub翻译组:孟翔杰 本文分享自微信公众号 - DeepHub IMBA(deephub-imba)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

AudioContext技术和音乐可视化(2)

Intro 转载请注明来源,可以在测试博客查看完成效果。 本篇讲述如何绘制动态的星空,其实关联到频域数据已经没什么悬念了。 一、使用Canvas绘图 1.1 位置和大小 绘制背景的第一要务便是把canvas元素放置在背景这一层次上,避免遮盖其他元素。 对我而言,个人习惯用css来设置大小和位置,用html来确定渲染顺序而不是z-index。 下面是html代码。 <html> <body> <canvas id="background-canvas"></canvas> <!-- other elements --> </body> </html> 下面是css代码。 #background-canvas { position: fixed; left: 0; top: 0; width: 100vw; height: 100vh; background-color: black; } fixed确保拖动页面不会令背景也跟随移动。 其余部分我想应该没什么有疑问的地方。 1.2 CanvasContext2D 对于canvas元素的绘图操作我想很多人应该接触过。 以绘制圆形为例,使用如下代码。 const canvas = document.getElementById("background-canvas"); const ctx = canvas.getContext("2d"); ctx.fillStyle='#fff'; ctx.beginPath(); ctx.arc(100,100,50,0,Math.PI*2); // 参数分别为坐标x,y,半径,起始弧度,结束弧度 ctx.fill(); 这样就画完了一个实心圆。 需要注意,canvas的大小通过css设置可能导致画面被拉伸变形模糊,所以最好的办法是绘制前确定一下canvas的大小。 此外需要注意的是,重置大小会导致画面清空,用这种方式可以替代fillRect或者clearRect,有的浏览器平台更快但也有浏览器更慢。可以查阅这篇博文来参考如何提升canvas绘图性能。 fillStyle可以使用css的颜色代码,也就是说我们可以写下诸如rgba、hsla之类的颜色,这给我们编写代码提供了很多方便。 1.3 绘制星星 星空是由星星组成的这显然不用多说了,先来看如何绘制单个星星。 星星的绘制方法很多,贴图虽然便利但显然不够灵活,我们的星星是要随节奏改变亮度和大小的,利用贴图的话就只能在alpha值和drawImage缩放来处理了。虽然是一种不错的办法,不过这里我使用了RadialGradient来控制绘图。 PS:RadialGradient 的性能比较差,大量使用会导致明显的性能下降,这是一个显著降低绘制效率的地方。 那么,我们先画一个圆(加点细节预警)。 const canvas = document.getElementById("background-canvas"); const ctx = canvas.getContext("2d"); // 确保不会变形 canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; // 参数分别为起始坐标x,y,半径,结束坐标x,y,半径 const gradient = ctx.createRadialGradient(100, 100, 0, 100, 100, 50); gradient.addColorStop(0.025, "#fff"); // 中心的亮白色 gradient.addColorStop(0.1, "rgba(255, 255, 255, 0.9)"); // 核心光点和四周的分界线 gradient.addColorStop(0.25, "hsla(198, 66%, 75%, 0.9)"); // 核心亮点往四周发散的蓝光 gradient.addColorStop(0.75, "hsla(198, 64%, 33%, 0.4)"); // 蓝光边缘 gradient.addColorStop(1, "hsla(198, 64%, 33%, 0)"); // 淡化直至透明 ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(100, 100, 50, 0, Math.PI * 2); ctx.fill(); 可以在codepen查看效果或直接编辑你的星(圈)星(圈)。 看上去还不错? 让我们用代码控制它的亮度和大小。 const canvas = document.getElementById("background-canvas"); const ctx = canvas.getContext("2d"); // 确保不会变形 canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; // 通过energy控制亮度和大小 let energy = 255; let radius = 50; let energyChangeRate = -1; function draw() { requestAnimationFrame(draw); // 定时绘制,requestAnimationFrame比setTimeout更好。 energy += energyChangeRate; // 见过呼吸灯吧?我们让它变亮~再变暗~反复循环~ if (energy <= 0 || energy >= 255) energyChangeRate = -energyChangeRate; // 计算出当前的大小 const r = radius + energy * 0.1; // 清空屏幕 ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); // 参数分别为起始坐标x,y,半径,结束坐标x,y,半径 const gradient = ctx.createRadialGradient(100, 100, 0, 100, 100, r); gradient.addColorStop(0.025, "#fff"); // 中心的亮白色 gradient.addColorStop(0.1, "rgba(255, 255, 255, 0.9)"); // 核心光点和四周的分界线 gradient.addColorStop(0.25, `hsla(198, 66%, ${Math.min(75+energy*0.01,100)}%, 0.9)`); // 核心亮点往四周发散的蓝光 gradient.addColorStop(0.75, `hsla(198, 64%, ${Math.min(33+energy*0.01,100)}%, 0.4)`); // 蓝光边缘 gradient.addColorStop(1, "hsla(198, 64%, 33%, 0)"); // 淡化直至透明 ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(100, 100, r, 0, Math.PI * 2); ctx.fill(); } draw(); 可以在codepen查看并编辑效果。 1.4 封装星星 通常来说粒子系统不大会把单个粒子封装成类,因为函数调用的开销还是蛮大的。。。 不过在这里我们这里就先这样了,方便理解和阅读。渲染的瓶颈解决之前,粒子函数调用这点开销根本不是回事儿。 const canvas = document.getElementById("background-canvas"); const ctx = canvas.getContext("2d"); // 确保不会变形 canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; // 用javascript原生的class而不是prototype class Star { constructor(x, y, radius, lightness) { this.radius = radius; this.x = x; this.y = y; this.lightness; } draw(ctx, energy) { // 计算出当前的大小 const r = this.radius + energy * 0.1; // 参数分别为起始坐标x,y,半径,结束坐标x,y,半径 const gradient = ctx.createRadialGradient( this.x, this.y, 0, this.x, this.y, r ); gradient.addColorStop(0.025, "#fff"); // 中心的亮白色 gradient.addColorStop(0.1, "rgba(255, 255, 255, 0.9)"); // 核心光点和四周的分界线 gradient.addColorStop( 0.25, `hsla(198, 66%, ${Math.min(75 + energy * 0.01, 100)}%, 0.9)` ); // 核心亮点往四周发散的蓝光 gradient.addColorStop( 0.75, `hsla(198, 64%, ${Math.min(33 + energy * 0.01, 100)}%, 0.4)` ); // 蓝光边缘 gradient.addColorStop(1, "hsla(198, 64%, 33%, 0)"); // 淡化直至透明 ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(this.x, this.y, r, 0, Math.PI * 2); ctx.fill(); } } const star = new Star(100, 100, 50); let energy = 255; let energyChangeRate = -1; // 渲染函数来循环渲染! function render() { requestAnimationFrame(render); energy += energyChangeRate; if (energy <= 0 || energy >= 255) energyChangeRate = -energyChangeRate; // 清空屏幕 ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); star.draw(ctx, energy); } // 开始渲染动画! render(); 可以在codepen查看代码效果。 完成! 1.5 银河 绘制银河的核心在于随机分布的星星绕着同一中心点旋转,分为两步来讲,第一步是随机分布,这很简单,用Math.random就好了。 // star 部分略 class Galaxy { constructor(canvas) { this.stars = []; this.canvas = canvas; this.ctx = canvas.getContext("2d"); this.energy = 255; this.energyChangeRate = -2; } init(num) { for (let i = 0; i < num; i++) { this.stars.push( // 随机生成一定数量的星星,初始化星星位置和大小。 new Star( Math.random() * this.canvas.width, Math.random() * this.canvas.height, Math.random() * 10 + 1, Math.random() * 30 + 33 ) ); } } render() { this.energy += this.energyChangeRate; if (this.energy <= 0 || this.energy >= 255) this.energyChangeRate = -this.energyChangeRate; // 清空屏幕 this.ctx.fillStyle = "black"; this.ctx.fillRect(0, 0, canvas.width, canvas.height); for (const star of this.stars) { star.draw(this.ctx, this.energy); } } } const canvas = document.getElementById("background-canvas"); // 确保不会变形 canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; const galaxy = new Galaxy(canvas); galaxy.init(50); function render() { requestAnimationFrame(render); galaxy.render(); } render(); 可以在codepen查看效果和完整代码。 1.6 旋转起来! 【加点细节预警】 接下来我们为星星准备轨道参数,让它们动起来! 首先修改Star类,加入几个字段。 class Star { constructor(x, y, radius, lightness, orbit, speed, t) { this.radius = radius; this.x = x; this.y = y; this.lightness; this.orbit = orbit; // 轨道 this.speed = speed; // 运动速度 this.t = t; // 三角函数x轴参数,用 sin/cos 组合计算位置 } // 下略 } 修改初始化代码。 // 前略 init(num) { const longerAxis = Math.max(this.canvas.width, this.canvas.height); const diameter = Math.round( Math.sqrt(longerAxis * longerAxis + longerAxis * longerAxis) ); const maxOrbit = diameter / 2; for (let i = 0; i < num; i++) { this.stars.push( // 随机生成一定数量的星星,初始化星星位置和大小。 new Star( Math.random() * this.canvas.width, Math.random() * this.canvas.height, Math.random() * 10 + 1, Math.random() * 30 + 33, Math.random() * maxOrbit, // 随机轨道 Math.random() / 1000, // 随机速度 Math.random() * 100 // 随机位置 ) ); } // 后略 然后在Galaxy里加入控制移动的代码。 move() { for (const star of this.stars) { console.log(star.orbit) star.x = this.canvas.width/2+ Math.cos(star.t) * star.orbit; star.y = this.canvas.height/2+ Math.sin(star.t) * star.orbit/2; star.t += star.speed; } 然后每一帧进行移动! function render() { requestAnimationFrame(render); galaxy.render(); galaxy.move(); // 动起来! } 大功告成! 在codepen查看完整源码! 1.7 待续 PS:不保证粘贴的代码都能跑,反正codepen上是都能的。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册