深度学习笔记之循环神经网络(八)LSTM的轻量级变体——门控循环单元(GRU)

news2024/10/1 12:22:23

引言

上一节介绍了从反向传播过程的角度认识 LSTM \text{LSTM} LSTM如何抑制梯度消失的问题。本节以 LSTM \text{LSTM} LSTM的问题为引,介绍它的一种轻量级变体——门控循环单元。

回顾: LSTM \text{LSTM} LSTM的前馈计算过程

关于 LSTM \text{LSTM} LSTM的结构展开图与前馈计算过程表示如下:
LSTM结构展开图
对应一个单元 ( Cell ) (\text{Cell}) (Cell)的前馈计算过程:
{ f ( t ) = σ [ W H ⇒ F ⋅ h ( t − 1 ) + W X ⇒ F ⋅ x ( t ) + b F ] i ( t ) = σ [ W H ⇒ I ⋅ h ( t − 1 ) + W X ⇒ I ⋅ x ( t ) + b I ] C ~ ( t ) = Tanh [ W H ⇒ C ~ ⋅ h ( t − 1 ) + W X ⇒ C ~ ⋅ x ( t ) + b C ~ ] C ( t ) = f ( t ) ∗ C ( t − 1 ) + i t ∗ C ~ ( t ) o ( t ) = σ [ W H ⇒ O ⋅ h ( t − 1 ) + W X ⇒ O ⋅ x ( t ) + b O ] h ( t ) = o ( t ) ∗ Tanh ( C ( t ) ) \begin{cases} \begin{aligned} & f^{(t)} = \sigma \left[\mathcal W_{\mathcal H \Rightarrow \mathcal F} \cdot h^{(t-1)} + \mathcal W_{\mathcal X \Rightarrow \mathcal F} \cdot x^{(t)} + b_{\mathcal F}\right] \\ & i^{(t)} = \sigma \left[\mathcal W_{\mathcal H \Rightarrow \mathcal I} \cdot h^{(t-1)} + \mathcal W_{\mathcal X \Rightarrow \mathcal I} \cdot x^{(t)} + b_{\mathcal I}\right] \\ & \widetilde{\mathcal C}^{(t)} = \text{Tanh} \left[\mathcal W_{\mathcal H \Rightarrow \widetilde{\mathcal C}} \cdot h^{(t-1)} + \mathcal W_{\mathcal X \Rightarrow \widetilde{\mathcal C}} \cdot x^{(t)} + b_{\widetilde{\mathcal C}}\right] \\ & \mathcal C^{(t)} = f^{(t)} * \mathcal C^{(t-1)} + i_t * \widetilde{\mathcal C}^{(t)} \\ & o^{(t)} = \sigma \left[\mathcal W_{\mathcal H \Rightarrow \mathcal O} \cdot h^{(t-1)} + \mathcal W_{\mathcal X \Rightarrow \mathcal O} \cdot x^{(t)} + b_{\mathcal O}\right] \\ & h^{(t)} = o^{(t)} * \text{Tanh}(\mathcal C^{(t)}) \end{aligned} \end{cases} f(t)=σ[WHFh(t1)+WXFx(t)+bF]i(t)=σ[WHIh(t1)+WXIx(t)+bI]C (t)=Tanh[WHC h(t1)+WXC x(t)+bC ]C(t)=f(t)C(t1)+itC (t)o(t)=σ[WHOh(t1)+WXOx(t)+bO]h(t)=o(t)Tanh(C(t))
对应的权重参数有:
θ = { W H ⇒ ⋅ : W H ⇒ F , W H ⇒ I , W H ⇒ C ~ , W H ⇒ O W X ⇒ ⋅ : W X ⇒ F , W X ⇒ I , W X ⇒ C ~ , W X ⇒ O b : b F , b I , b O , b C ~ \theta = \begin{cases} \mathcal W_{\mathcal H \Rightarrow \cdot} :\mathcal W_{\mathcal H \Rightarrow \mathcal F},\mathcal W_{\mathcal H \Rightarrow \mathcal I},\mathcal W_{\mathcal H \Rightarrow \widetilde{\mathcal C}},\mathcal W_{\mathcal H \Rightarrow \mathcal O} \\ \mathcal W_{\mathcal X \Rightarrow \cdot }:\mathcal W_{\mathcal X \Rightarrow \mathcal F},\mathcal W_{\mathcal X \Rightarrow \mathcal I},\mathcal W_{\mathcal X \Rightarrow \widetilde{\mathcal C}},\mathcal W_{\mathcal X \Rightarrow \mathcal O} \\ b:b_{\mathcal F},b_{\mathcal I},b_{\mathcal O},b_{\widetilde{\mathcal C}} \end{cases} θ= WH:WHF,WHI,WHC ,WHOWX:WXF,WXI,WXC ,WXOb:bF,bI,bO,bC

该结构相比于循环神经网络 ( Recurrent Neural Network,RNN ) (\text{Recurrent Neural Network,RNN}) (Recurrent Neural Network,RNN)在反向传播过程中,每一个时刻的前项传递过程,对应的参数均会有指数级别的梯度传播路径,并且反向传播过程中各门控结构的输出直接参与反向传播的计算。这种方式有效抑制了梯度消失问题——从梯度累加数量门控结构的调节角度都可以使各时刻有梯度进行反向传播。

LSTM \text{LSTM} LSTM的问题

虽然 LSTM \text{LSTM} LSTM能够抑制梯度消失问题,但需要以增加时间复杂度和空间复杂度作为代价:

  • 梯度越向初始时刻方向传播,关于各参数梯度的累加项越多(指数级别增长),它的梯度计算过程越困难;
  • 相比于循环神经网络的权重参数, LSTM \text{LSTM} LSTM需要消耗更多的内存空间存储并更新参数信息。
    这里与 LSTM \text{LSTM} LSTM的部分相对应,仅描述‘序列信息传递过程’。
    θ r = { W H ⇒ H , W X ⇒ H , b H } \theta_r = \{\mathcal W_{\mathcal H \Rightarrow \mathcal H},\mathcal W_{\mathcal X \Rightarrow \mathcal H},b_{\mathcal H}\} θr={WHH,WXH,bH}

并且包含更多类型参数的模型也会更加复杂。从而可能导致过拟合( Overfitting \text{Overfitting} Overfitting)的现象发生。基于此,我们观察门控循环单元 ( Gated Recurrent Unit,GRU ) (\text{Gated Recurrent Unit,GRU}) (Gated Recurrent Unit,GRU)是如何优化该问题的。

GRU \text{GRU} GRU的前馈计算过程

GRU的结构展开图
关于 GRU \text{GRU} GRU前馈计算过程表示如下:
{ Z ( t ) = σ [ W H ⇒ Z ⋅ h ( t − 1 ) + W X ⇒ Z ⋅ x ( t ) + b Z ] r ( t ) = σ [ W H ⇒ r ⋅ h ( t − 1 ) + W X ⇒ r ⋅ x ( t ) + b r ] h ~ ( t ) = Tanh [ W H ⇒ H ~ ⋅ ( r ( t ) ∗ h ( t − 1 ) ) + W X ⇒ H ~ ⋅ x ( t ) + b H ~ ] h ( t ) = ( 1 − Z ( t ) ) ∗ h ( t − 1 ) + Z ( t ) ∗ h ~ ( t ) \begin{cases} \begin{aligned} & \mathcal Z^{(t)} = \sigma \left[\mathcal W_{\mathcal H \Rightarrow \mathcal Z} \cdot h^{(t-1)} + \mathcal W_{\mathcal X \Rightarrow \mathcal Z} \cdot x^{(t)} + b_{\mathcal Z}\right] \\ & r^{(t)} = \sigma \left[\mathcal W_{\mathcal H \Rightarrow r} \cdot h^{(t-1)} + \mathcal W_{\mathcal X \Rightarrow r} \cdot x^{(t)} + b_r\right] \\ & \widetilde{h}^{(t)} = \text{Tanh} \left[\mathcal W_{\mathcal H \Rightarrow \widetilde{\mathcal H}} \cdot (r^{(t)} * h^{(t-1)}) + \mathcal W_{\mathcal X \Rightarrow \widetilde{\mathcal H}} \cdot x^{(t)} + b_{\widetilde{\mathcal H}}\right] \\ & h^{(t)} = (1 - \mathcal Z^{(t)}) * h^{(t-1)} + \mathcal Z^{(t)} * \widetilde{h}^{(t)} \end{aligned} \end{cases} Z(t)=σ[WHZh(t1)+WXZx(t)+bZ]r(t)=σ[WHrh(t1)+WXrx(t)+br]h (t)=Tanh[WHH (r(t)h(t1))+WXH x(t)+bH ]h(t)=(1Z(t))h(t1)+Z(t)h (t)

从结构图与公式角度观察 GRU \text{GRU} GRU LSTM \text{LSTM} LSTM之间的差别:

  • 相比于 LSTM \text{LSTM} LSTM GRU \text{GRU} GRU删除了细胞状态 ( Cell State ) (\text{Cell State}) (Cell State),和循环神经网络相同,只有一种序列信息 h ( t ) ( t = 1 , 2 , ⋯   , T ) h^{(t)}(t=1,2,\cdots,\mathcal T) h(t)(t=1,2,,T)在各时刻之间传递;
  • 相比于 LSTM \text{LSTM} LSTM GRU \text{GRU} GRU少了一个门控结构,从而减少了一对权重矩阵 W H ⇒ ⋅ , W X ⇒ ⋅ \mathcal W_{\mathcal H \Rightarrow \cdot},\mathcal W_{\mathcal X \Rightarrow \cdot} WH,WX和偏置项 b . b_. b.

其中 Z ( t ) \mathcal Z^{(t)} Z(t)被称作更新门 ( Update Gate ) (\text{Update Gate}) (Update Gate) r ( t ) r^{(t)} r(t)被称作重置门 ( Reset Gate ) (\text{Reset Gate}) (Reset Gate) LSTM \text{LSTM} LSTM GRU \text{GRU} GRU逻辑上的核心区别有:

  • LSTM \text{LSTM} LSTM各门控结构 f ( t ) , i ( t ) , o ( t ) f^{(t)},i^{(t)},o^{(t)} f(t),i(t),o(t)细胞状态 C ~ ( t ) \widetilde{\mathcal C}^{(t)} C (t)之间的训练过程相互独立;仅在融合过程中对各神经元的输出分布进行运算:
    上述 4 4 4个隐变量中的输入均是 h ( t − 1 ) , x ( t ) h^{(t-1)},x^{(t)} h(t1),x(t);并且学习过程中,各神经元互不干扰。
    C ( t ) = f ( t ) ∗ C ( t − 1 ) + i t ∗ C ~ ( t ) h ( t ) = o ( t ) ∗ Tanh ( C ( t ) ) \mathcal C^{(t)} = f^{(t)} * \mathcal C^{(t-1)} + i_t * \widetilde{\mathcal C}^{(t)} \\ h^{(t)}= o^{(t)} * \text{Tanh}(\mathcal C^{(t)}) C(t)=f(t)C(t1)+itC (t)h(t)=o(t)Tanh(C(t))

  • GRU \text{GRU} GRU的细胞单元中,关于当前时刻的候选状态 h ~ ( t ) \widetilde{h}^{(t)} h (t)的训练过程中,其输入就已经被挑选过了
    h ~ ( t ) = Tanh [ W H ⇒ H ~ ⋅ ( r ( t ) ∗ h ( t − 1 ) ) + W X ⇒ H ~ ⋅ x ( t ) + b H ~ ] \widetilde{h}^{(t)} = \text{Tanh} \left[\mathcal W_{\mathcal H \Rightarrow \widetilde{\mathcal H}} \cdot (r^{(t)} * h^{(t-1)}) + \mathcal W_{\mathcal X \Rightarrow \widetilde{\mathcal H}} \cdot x^{(t)} + b_{\widetilde{\mathcal H}}\right] h (t)=Tanh[WHH (r(t)h(t1))+WXH x(t)+bH ]
    很明显, r ( t ) ∗ h ( t − 1 ) r^{(t)} * h^{(t-1)} r(t)h(t1)相当于仅将未被遗忘的序列信息进行训练,而 ( 1 − r ( t ) ) ∗ h ( t − 1 ) (1 - r^{(t)}) * h^{(t-1)} (1r(t))h(t1)就已经被遗忘了。基于这种机制,使得候选状态 h ~ ( t ) \widetilde{h}^{(t)} h (t)的分布结果比 C ~ ( t ) \widetilde{\mathcal C}^{(t)} C (t)更有价值(指向性)。逻辑上就没有必要再使用类似输入门结构对其进行约束了。
    一个是对‘输出分布’进行挑选,另一个是在输入分布时进行挑选。

    虽然使用了更精炼的输入分布,但该神经元的作用依然是求解当前时刻候选信息的后验概率分布 P ( h ~ ( t ) ∣ h ( t − 1 ) , x ( t ) ) \mathcal P(\widetilde{h}^{(t)} \mid h^{(t-1)},x^{(t)}) P(h (t)h(t1),x(t))。因此,和 LSTM \text{LSTM} LSTM一样,最终输出 h ( t ) h^{(t)} h(t)依然要对 h ( t − 1 ) h^{(t-1)} h(t1) h ~ ( t ) \widetilde{h}^{(t)} h (t)进行重新配比。但是这个配比相比之下简单很多。因为: h ( t − 1 ) h^{(t-1)} h(t1)由各时刻的候选状态 h ~ ( t ) ( t = 1 , 2 , ⋯   ) \widetilde{h}^{(t)}(t=1,2,\cdots) h (t)(t=1,2,)组成,而每个时刻求解候选状态 h ~ ( t ) \widetilde{h}^{(t)} h (t)的过程中,均已经将不必要的信息进行遗忘,因而不需要再对 h ( t − 1 ) h^{(t-1)} h(t1)再执行遗忘
    h ( t ) = ( 1 − Z ( t ) ) ∗ h ( t − 1 ) + Z ( t ) ∗ h ~ ( t ) h^{(t)} = (1 - \mathcal Z^{(t)}) * h^{(t-1)} + \mathcal Z^{(t)} * \widetilde{h}^{(t)} h(t)=(1Z(t))h(t1)+Z(t)h (t)

    个人理解:
    输入门 i ( t ) i^{(t)} i(t)是遗忘门 f ( t ) f^{(t)} f(t)对称操作
    LSTM \text{LSTM} LSTM中,对于过去时刻的序列信息 C ( t − 1 ) \mathcal C^{(t-1)} C(t1)候选信息 C ~ ( t ) \widetilde{\mathcal C}^{(t)} C (t):
    { C ( t − 1 ) = f ( t − 1 ) ∗ C ( t − 2 ) + i ( t − 1 ) ∗ C ~ ( t − 1 ) C ~ ( t ) = Tanh [ W h ( t − 1 ) ⇒ C ~ ( t ) ⋅ h ( t − 1 ) + W x ( t ) ⇒ C ~ ( t ) ⋅ x ( t ) + b C ~ ] \begin{cases} \mathcal C^{(t-1)} = f^{(t-1)} * \mathcal C^{(t-2)} + i^{(t-1)} * \widetilde{\mathcal C}^{(t-1)} \\ \widetilde{\mathcal C}^{(t)} = \text{Tanh} \left[\mathcal W_{h^{(t-1)} \Rightarrow\widetilde{\mathcal C}^{(t)}} \cdot h^{(t-1)} + \mathcal W_{x^{(t)} \Rightarrow \widetilde{\mathcal C}^{(t)}} \cdot x^{(t)} + b_{\widetilde{\mathcal C}}\right] \end{cases} {C(t1)=f(t1)C(t2)+i(t1)C (t1)C (t)=Tanh[Wh(t1)C (t)h(t1)+Wx(t)C (t)x(t)+bC ]
    它们的输入均是 h ( τ ) , x ( τ ) ( τ ∈ { 1 , 2 , ⋯ T } ) h^{(\tau)},x^{(\tau)}(\tau \in \{1,2,\cdots \mathcal T\}) h(τ),x(τ)(τ{1,2,T}),因而在计算对应后验概率分布的过程中,它们到底使用哪些信息作为条件,我们是不可探究的;
    其中 x ( τ ) x^{(\tau)} x(τ)是输入特征,不作考虑;但 h ( τ ) h^{(\tau)} h(τ)作为序列信息,在表示 C ( t − 1 ) . C ~ ( t ) \mathcal C^{(t-1)}.\widetilde{\mathcal C}^{(t)} C(t1).C (t)后验的各神经元之间无交集,各自使用哪些‘过去信息’进行学习,未知,都有可能;

    GRU \text{GRU} GRU中, h ( t − 1 ) , h ~ ( t ) h^{(t-1)},\widetilde{h}^{(t)} h(t1),h (t)的输入均是被挑选(未被遗忘)的优质信息,导致它们的后验分布相比于之前的不可探究,更有指向性。因此,遗忘门输入门这一对相辅相成的门控结构都被省略掉了。

    Z ( t ) \mathcal Z^{(t)} Z(t)不是输入门,它仅仅是在 Sigmoid \text{Sigmoid} Sigmoid激活函数的值域 ( 0 , 1 ) (0,1) (0,1)下,权衡 h ( t − 1 ) h^{(t-1)} h(t1) h ~ ( t ) \widetilde{h}^{(t)} h (t)之间比例关系的一个比率系数而已。

    其中 Z ( t ) \mathcal Z^{(t)} Z(t)仅表示学习出的一个比例系数;而 1 − Z ( t ) 1- \mathcal Z^{(t)} 1Z(t)是基于 Sigmoid \text{Sigmoid} Sigmoid激活函数的值域描述的 Z ( t ) \mathcal Z^{(t)} Z(t)之外剩下的比例结果。将 h ( t − 1 ) h^{(t-1)} h(t1) h ~ ( t ) \widetilde{h}^{(t)} h (t)之间的比例进行调整,并将最终的和作为输出。

GRU \text{GRU} GRU的优势

首先, GRU \text{GRU} GRU的参数更少,从而有效降低过拟合的风险;并且在反向传播的过程中,随着反向传播深度的加深,对应需要反向传播路径相比于 LSTM \text{LSTM} LSTM大量减少。从而减小了时间、空间复杂度的负担

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/585214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【29】核心易中期刊推荐——计算语言学人工智能(AI)技术

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

使用javascript-obfuscator给js文件加密

一、安装javascript-obfuscator包 npm install javascript-obfuscator -g二、默认配置直接压缩文件 javascript-obfuscator miniprogram/src/utils/utils_create_sign.js --output miniprogram/src/utils/create_sign.js三、根据配置文件压缩文件 3.1、创建mixs.json配置文…

前端阿里云OSS直传,微信小程序版本

前言: 网络上许多的文章资料,全是使用阿里云官方的SDK,ali-oss插件去做直传。可是各位素未谋面的朋友要注意,这个SDK它支持web环境使用,也就是PC端浏览器。 当项目环境切换到微信小程序,是无法使用这种方…

Power BI Embedded自动缩放容量,为公司每个月节省上万元

哎,不知道今年行情怎么就这样了,大厂一边大批毕业生,一边大量招人。难道是今年的新人便宜?就连道哥(吴翰清,阿里P10,中国顶级黑客)都从阿里离职了,当年年少不懂学计算机&…

Nodejs批量处理图片小工具:批量修改图片信息

小工具一:批量修改文件夹里面的图片名称 步骤: 1.安装nodejs。 2.根据需要修改editFileName(filePath, formatName)函数的参数,也可以不改,直接将renameFile.js和img文件夹放在同一个目录下。 3.在renameFile.js目录下开启终端…

SQL报错this is incompatible with sql_mode=only_full_group_by

一、bug记录 1.1.bug截图 1.2.sql语句 SELECT id,batch_no,if_code,channel_mch_no,bill_date,bill_type,currency,order_id, channel_order_no,channel_amount,channel_fee_amount,channel_success_at, channel_user,channel_state,org_pay_order_id,channel_refund_amoun…

曾经由盛转衰的骈文,却引领后人在文质兼美的创作之路上坚定前行

又叫骈体文,是和散文相对应的一种文体,它兴起于汉末,形成于魏晋,最盛行于南北朝,在初唐、中唐、唐末、五代、宋初时也盛极一时。古人语:两马并驾为骈,所以骈文最大的特点是用对偶的手法&#xf…

Fiddler抓包工具之fiddler设置手机端抓包

fiddler设置手机端抓包 安卓手机抓包 第一步:配置电脑和安卓的相关设置 1、手机和fiddler位于同一个局域网内;首先从fiddler处获取到ip地址和端口号: ,点击online,最后一行就是ip地址 2、路径:Tools》O…

数据库基础——10.子查询

这篇文章来讲一下数据库的子查询 目录 1. 需求分析与问题解决 1.1 实际问题 1.2 子查询的基本使用 1.3 子查询的分类 2. 单行子查询 2.1 单行比较操作符 2.2 代码示例 2.3 HAVING 中的子查询 2.4 CASE中的子查询 2.5 子查询中的空值问题 2.5 非法使用子查询​编辑…

数字IC验证高频面试问题整理(附答案)

后台有同学私信想要验证的面试题目,这不就来了~ Q1.权重约束中”:”和 /”的区别 : 操作符表示值范围内的每一个值的权重是相同的,比如[1:3]:40,表示1,2,3取到的概率为40/120; :/操作符表示权重要平均分到值范围内的…

spring security(密码编码器、授权,会话)

目录 密码编码器 授权决策 AffirmativeBased ConsensusBased UnanimousBased 授权 web授权 HttpSecurity常用方法及说明 方法授权 会话控制 会话超时 安全会话cookie 密码编码器 Spring Security为了适应多种多样的加密类型,又做了抽象,D…

虚拟机配置

配置虚拟机网络 创建虚拟机 20G 4G内存 初始化用户名和密码 zhao 123456 克隆拷贝2个虚拟机 配置内存为2G 修改主机名和固定IP hostnamectl set-hostname node1 hostnamectl set-hostname node2 vim /etc/sysconfig/network-scripts/ifcfg-ens33 systemctl stop network s…

渗透测试辅助工具箱

0x01 说明 渗透测试辅助工具箱 运行条件:jdk8 双击即可运行 反弹shell,命令生成器,自动编码,输入对应IP端口即可,实现一劳永逸,集成一些小工具,辅助渗透,提高效率 输入框说明 L…

TDengine 报错 failed to connect to server, reason: Unable to establish connection

一、前文 TDengine 入门教程——导读 二、遇到问题 taos 命令行(CLI)连接不上,进不去。 [rootiZ2ze30dygwd6yh7gu6lskZ ~]# taos Welcome to the TDengine Command Line Interface, Client Version:3.0.0.1 Copyright (c) 2022 by TDengine…

基于Azure实现Java访问OpenAI

之前使用了Java代码访问OpenAI:OpenAI注册以及Java代码调用_雨欲语的博客-CSDN博客但是需要vpn才能访问,现在可以基于微软的Azure访问OpenAI,不再需要vpn,官方文档:快速入门 - 开始通过 Azure OpenAI 服务使用 ChatGPT…

【国产虚拟仪器】基于JFM7K325T(复旦微FPGA)的高速数据采集平台

板卡概述 XM714是自主研制的一款5路HD-SDI视频采集图像处理平台,该平台采用上海复旦微的高性能Kintex系列FPGA加上华为海思的高性能视频处理器HI3531DV200来实现。 华为海思的HI3531DV200是一款集成了ARM A53四核处理器性能强大的神经网络引擎,支持多种…

python:容器:字符串——常用操作

字符串[下标]根据下标索引取出特定位置字符字符串.index(字符串)查找给定字符的第一个匹配项的下标字符串.replace(字符串1,字符串2) 将字符串内的全部字符串1,替换为字符串2 不会修改原字符串,而是得到一个新的 字符串.split(字符串) 按照给定字符串&am…

[高光谱]使用PyTorch的dataloader加载高光谱数据

本文实验的部分代码参考 Hyperspectral-Classificationhttps://github.com/eecn/Hyperspectral-Classification如果对dataloader的工作原理不太清楚可以参见 [Pytorch]DataSet和DataLoader逐句详解https://blog.csdn.net/weixin_37878740/article/details/129350390?spm1001…

使用Nextcloud搭建私人云盘,并内网穿透实现公网远程访问

文章目录 摘要视频教程1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 转载自cpolar极点云的文章:使用Nextcl…

好程序员:如果你从6月份开始学Java编程......

现在学习Java编程还来得及?好程序员可以明确的告诉你:当然了~新手入门快,非常容易学。Java计算机语言也是一门面向对象的语言,更加符合人类的思想,所求皆对象,并没有指针等一些难理解的知识。Java覆盖面宽、…