-
2018-07-09 12:14:40
一、生成句法分析树
把一句话按照句法逻辑组织成一棵树,由人来做这件事是可行的,但是由机器来实现是不可思议的,然而算法世界就是这么神奇,把一个十分复杂的过程抽象成仅仅几步操作,甚至不足10行代码,就能让机器完成需要耗费人脑几十亿脑细胞的工作,本文我们来见识一下神奇的句法分析树生成算法
请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址
句法分析
先来解释一下句法分析。句法分析分为句法结构分析和依存关系分析。
句法结构分析也就是短语结构分析,比如提取出句子中的名次短语、动词短语等,最关键的是人可以通过经验来判断的短语结构,那么怎么由机器来判断呢?
(有关依存关系分析的内容,具体可以看《依存句法以及语义依存分析》)
句法分析树
样子如下:
-吃(v)-
| |
我(rr) 肉(n)
句法结构分析基本方法
分为基于规则的分析方法和基于统计的分析方法。基于规则的方法存在很多局限性,所以我们采取基于统计的方法,目前最成功的是基于概率上下文无关文法(PCFG)。基于PCFG分析需要有如下几个要素:终结符集合、非终结符集合、规则集。
相对于先叙述理论再举实例的传统讲解方法,我更倾向于先给你展示一个简单的例子,先感受一下计算过程,然后再叙述理论,这样会更有趣。
例子是这样的:我们的终结符集合是:∑={我, 吃, 肉,……},这个集合表示这三个字可以作为句法分析树的叶子节点,当然这个集合里还有很多很多的词
我们的非终结符集合是:N={S, VP, ……},这个集合表示树的非页子节点,也就是连接多个节点表达某种关系的节点,这个集合里也是有很多元素
我们的规则集:R={
NN->我 0.5
Vt->吃 1.0
NN->肉 0.5
VP->Vt NN 1.0
S->NN VP 1.0
……
}
这里的句法规则符号可以参考词性标注,后面一列是模型训练出来的概率值,也就是在一个固定句法规则中NN的位置是“我”的概率是0.5,NN推出“肉”的概率是0.5,0.5+0.5=1,也就是左部相同的概率和一定是1。不知道你是否理解了这个规则的内涵
再换一种方法解释一下,有一种句法规则是:
S——|
| |
NN VP
|——|
Vt NN
其中NN的位置可能是“我”,也可能是“肉”,是“我”的概率是0.5,是“肉”的概率是0.5,两个概率和必为1。其中Vt的位置一定是“吃”,也就是概率是1.0……。这样一说是不是就理解了?
规则集里实际上还有很多规则,只是列举出会用到的几个
以上的∑、N、R都是经过机器学习训练出来的数据集及概率,具体训练方法下面我们会讲到
那么如何根据以上的几个要素来生成句法分析树呢?
(1)“我”
词性是NN,推导概率是0.5,树的路径是“我”
(2)“吃”
词性是Vt,推导概率是1.0,树的路径是“吃”
(3)“肉”
词性是NN,概率是0.5,和Vt组合符合VP规则,推导概率是0.5*1.0*1.0=0.5,树的路径是“吃肉”
NN和VP组合符合S规则,推导概率是0.5*0.5*1.0=0.25,树的路径是“我吃肉”
所以最终的树结构是:
S——|
| |
NN VP
我 |——|
Vt NN
吃 肉
上面的例子是比较简单的,实际的句子会更复杂,但是都是通过这样的动态规划算法完成的
提到动态规划算法,就少不了“选择”的过程,一句话的句法结构树可能有多种,我们只选择概率最大的那一种作为句子的最佳结构,这也是“基于概率”上下文无关文法的名字起源。
上面的计算过程总结起来就是:设W={ω1ω2ω3……}表示一个句子,其中的ω表示一个词(word),利用动态规划算法计算非终结符A推导出W中子串ωiωi+1ωi+2……ωj的概率,假设概率为αij(A),那么有如下递归公式:
αij(A)=P(A->ωi)
αij(A)=∑∑P(A->BC)αik(B)α(k+1)j(C)
以上两个式子好好理解一下其实就是上面“我吃肉”的计算过程
以上过程理解了之后你一定会问,这里面最关键的的非终结符、终结符以及规则集是怎么得来的,概率又是怎么确定的?下面我们就来说明
句法规则提取方法与PCFG的概率参数估计
这部分就是机器学习的知识了,有关机器学习可以参考《机器学习教程》
首先我们需要大量的树库,也就是训练数据。然后我们把树库中的句法规则提取出来生成我们想要的结构形式,并进行合并、归纳等处理,最终得到上面∑、N、R的样子。其中的概率参数计算方法是这样的:
先给定参数为一个随机初始值,然后采用EM迭代算法,不断训练数据,并计算每条规则使用次数作为最大似然计算得到概率的估值,这样不断迭代更新概率,最终得出的概率可以认为是符合最大似然估计的精确值。
总结一下
句法分析树生成算法是基于统计学习的原理,根据大量标注的语料库(树库),通过机器学习算法得出非终结符、终结符、规则集及其概率参数,然后利用动态规划算法生成每一句话的句法分析树,在句法分析树生成过程中如果遇到多种树结构,选择概率最大的那一种作为最佳句子结构
二、从一个小例子来看词义消歧
日后再说这个成语到了当代可以说含义十分深刻,你懂的,但是如何让计算机懂得可能有两种含义的一个词到底是想表达哪个含义呢?这在自然语言处理中叫做词义消歧,从本节开始我们从基本的结构分析跨入语义分析,开始让计算机对语言做深层次的理解
词义消歧
词义消歧是句子和篇章语义理解的基础,是必须解决的问题。任何一种语言都有大量具有多种含义的词汇,中文的“日”,英文的“bank”,法语的“prendre”……。
词义消歧可以通过机器学习的方法来解决。谈到机器学习就会分成有监督和无监督的机器学习。词义消歧有监督的机器学习方法也就是分类算法,即判断词义所属的分类。词义消歧无监督的机器学习方法也就是聚类算法,把词义聚成多类,每一类是一种含义。
有监督的词义消歧方法
基于互信息的词义消歧方法
这个方法的名字不好理解,但是原理却非常简单:用两种语言对照着看,比如:中文“打人”对应英文“beat a man”,而中文“打酱油”对应英文“buy some sauce”。这样就知道当上下文语境里有“人”的时候“打”的含义是beat,当上下文语境里有“酱油”的时候“打”的含义是buy。按照这种思路,基于大量中英文对照的语料库训练出来的模型就可以用来做词义消歧了,这种方法就叫做基于“互信息”的词义消歧方法。讲到“互信息”还要说一下它的起源,它来源于信息论,表达的是一个随机变量中包含另一个随机变量的信息量(也就是英文信息中包含中文信息的信息量),假设两个随机变量X、Y的概率分别是p(x), p(y),它们的联合分布概率是p(x,y),那么互信息计算公式是:
I(X; Y) = ∑∑p(x,y)log(p(x,y)/(p(x)p(y)))
以上公式是怎么推导出来的呢?比较简单,“互信息”可以理解为一个随机变量由于已知另一个随机变量而减少的不确定性(也就是理解中文时由于已知了英文的含义而让中文理解更确定了),因为“不确定性”就是熵所表达的含义,所以:
I(X; Y) = H(X) - H(X|Y)
等式后面经过不断推导就可以得出上面的公式,对具体推导过程感兴趣可以百度一下。
那么我们在对语料不断迭代训练过程中I(X; Y)是不断减小的,算法终止的条件就是I(X; Y)不再减小。
基于互信息的词义消歧方法自然对机器翻译系统的效果是最好的,但它的缺点是:双语语料有限,多种语言能识别出歧义的情况也是有限的(比如中英文同一个词都有歧义就不行了)。
基于贝叶斯分类器的消歧方法
提到贝叶斯那么一定少不了条件概率,这里的条件指的就是上下文语境这个条件,任何多义词的含义都是跟上下文语境相关的。假设语境(context)记作c,语义(semantic)记作s,多义词(word)记作w,那么我要计算的就是多义词w在语境c下具有语义s的概率,即:
p(s|c)
那么根据贝叶斯公式:
p(s|c) = p(c|s)p(s)/p(c)
我要计算的就是p(s|c)中s取某一个语义的最大概率,因为p(c)是既定的,所以只考虑分子的最大值:
s的估计=max(p(c|s)p(s))
因为语境c在自然语言处理中必须通过词来表达,也就是由多个v(词)组成,那么也就是计算:
max(p(s)∏p(v|s))
请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址
下面就是训练的过程了:
p(s)表达的是多义词w的某个语义s的概率,可以统计大量语料通过最大似然估计求得:
p(s) = N(s)/N(w)
p(v|s)表达的是多义词w的某个语义s的条件下出现词v的概率,可以统计大量语料通过最大似然估计求得:
p(v|s) = N(v, s)/N(s)
训练出p(s)和p(v|s)之后我们对一个多义词w消歧的过程就是计算(p(c|s)p(s))的最大概率的过程
无监督的词义消歧方法
完全无监督的词义消歧是不可能的,因为没有标注是无法定义是什么词义的,但是可以通过无监督的方法来做词义辨识。无监督的词义辨识其实也是一种贝叶斯分类器,和上面讲到的贝叶斯分类器消歧方法不同在于:这里的参数估计不是基于有标注的训练预料,而是先随机初始化参数p(v|s),然后根据EM算法重新估计这个概率值,也就是对w的每一个上下文c计算p(c|s),这样可以得到真实数据的似然值,回过来再重新估计p(v|s),重新计算似然值,这样不断迭代不断更新模型参数,最终得到分类模型,可以对词进行分类,那么有歧义的词在不同语境中会被分到不同的类别里。
仔细思考一下这种方法,其实是基于单语言的上下文向量的,那么我们进一步思考下一话题,如果一个新的语境没有训练模型中一样的向量怎么来识别语义?
这里就涉及到向量相似性的概念了,我们可以通过计算两个向量之间夹角余弦值来比较相似性,即:
cos(a,b) = ∑ab/sqrt(∑a^2∑b^2)
机器人是怎么理解“日后再说”的
回到最初的话题,怎么让机器人理解“日后再说”,这本质上是一个词义消歧的问题,假设我们利用无监督的方法来辨识这个词义,那么就让机器人“阅读”大量语料进行“学习”,生成语义辨识模型,这样当它听到这样一则对话时:
有一位老嫖客去找小姐,小姐问他什么时候结账啊。嫖客说:“钱的事情日后再说。”就开始了,完事后,小姐对嫖客说:“给钱吧。”嫖客懵了,说:“不是说日后再说吗?”小姐说:“是啊,你现在不是已经日后了吗?”
辨识了这里的“日后再说”的词义后,它会心的笑了
三、语义角色标注
浅层语义标注是行之有效的语言分析方法,基于语义角色的浅层分析方法可以描述句子中语义角色之间的关系,是语义分析的重要方法,也是篇章分析的基础,本节介绍基于机器学习的语义角色标注方法
语义角色
举个栗子:“我昨天吃了一块肉”,按照常规理解“我吃肉”应该是句子的核心,但是对于机器来说“我吃肉”实际上已经丢失了非常多的重要信息,没有了时间,没有了数量。为了让机器记录并提取出这些重要信息,句子的核心并不是“我吃肉”,而是以谓词“吃”为核心的全部信息。
“吃”是谓词,“我”是施事者,“肉”是受事者,“昨天”是事情发生的时间,“一块”是数量。语义角色标注就是要分析出这一些角色信息,从而可以让计算机提取出重要的结构化信息,来“理解”语言的含义。
语义角色标注的基本方法
语义角色标注需要依赖句法分析的结果进行,因为句法分析包括短语结构分析、浅层句法分析、依存关系分析,所以语义角色标注也分为:基于短语结构树的语义角色标注方法、基于浅层句法分析结果的语义角色标注方法、基于依存句法分析结果的语义角色标注方法。但无论哪种方法,过程都是:
句法分析->候选论元剪除->论元识别->论元标注->语义角色标注结果
其中论元剪除就是在较多候选项中去掉肯定不是论元的部分
其中论元识别是一个二值分类问题,即:是论元和不是论元
其中论元标注是一个多值分类问题
下面分别针对三种方法分别说明这几个过程的具体方法
基于短语结构树的语义角色标注方法
短语结构树是这样的结构:
S——| | | NN VP 我 |——| Vt NN 吃 肉
短语结构树里面已经表达了一种结构关系,因此语义角色标注的过程就是依赖于这个结构关系来设计的一种复杂策略,策略的内容随着语言结构的复杂而复杂化,因此我们举几个简单的策略来说明。
首先我们分析论元剪除的策略:
因为语义角色是以谓词为中心的,因此在短语结构树中我们也以谓词所在的节点为中心,先平行分析,比如这里的“吃”是谓词,和他并列的是“肉”,明显“肉”是受事者,那么设计什么样的策略能使得它成为候选论元呢?我们知道如果“肉”存在一个短语结构的话,那么一定会多处一个树分支,那么“肉”和“吃”一定不会在树的同一层,因此我们设计这样的策略来保证“肉”被选为候选论元:如果当前节点的兄弟节点和当前节点不是句法结构的并列关系,那么将它作为候选论元。当然还有其他策略不需要记得很清楚,现用现查就行了,但它的精髓就是基于短语结构树的结构特点来设计策略的。
然后就是论元识别过程了。论元识别是一个二值分类问题,因此一定是基于标注的语料库做机器学习的,机器学习的二值分类方法都是固定的,唯一的区别就是特征的设计,这里面一般设计如下特征效果比较好:谓词本身、短语结构树路径、短语类型、论元在谓词的位置、谓词语态、论元中心词、从属类别、论元第一个词和最后一个词、组合特征。
论元识别之后就是论元标注过程了。这又是一个利用机器学习的多值分类器进行的,具体方法不再赘述。
基于依存句法分析结果和基于语块的语义角色标注方法
这两种语义角色标注方法和基于短语结构树的语义角色标注方法的主要区别在于论元剪除的过程,原因就是他们基于的句法结构不同。
基于依存句法分析结果的语义角色标注方法会基于依存句法直接提取出谓词-论元关系,这和依存关系的表述是很接近的,因此剪除策略的设计也就比较简单:以谓词作为当前节点,当前节点所有子节点都是候选论元,将当前节点的父节点作为当前节点重复以上过程直至到根节点为止。
基于依存句法分析结果的语义角色标注方法中的论元识别算法的特征设计也稍有不同,多了有关父子节点的一些特征。
有了以上几种语义角色标注方法一定会各有优缺点,因此就有人想到了多种方法相融合的方法,融合的方式可以是:加权求和、插值……,最终效果肯定是更好,就不多说了。
更多相关内容 -
Polkadot验证节点的安全性和可用性
2019-05-16 18:29:45在本文中,我将在验证节点的安全性和可用性方面讨论两个主题。我知道,这里介绍的技巧仅仅涵盖了POS验证节点的“安全性和可用性”冰山一角。不过,我发现它们对于您的测试实例提供最小的安全性和可用性是有用的。 ...在本文中,我将在验证节点的安全性和可用性方面讨论两个主题。我知道,这里介绍的技巧仅仅涵盖了POS验证节点的“安全性和可用性”冰山一角。不过,我发现它们对于您的测试实例提供最小的安全性和可用性是有用的。
保护验证节点
在互联网上公开区块链或加密服务会吸引攻击者试图攻击您的系统。所以最好准备好采取任何措施来降低被危害的风险。
在运行我的polkadot验证节点时,我观察到大量的攻击者试图强行使用我的ssh密码。
我做的第一件事就是安装SSHGuard。那么什么是SSHGuard?正如Andrew Schartzmeyer在他的博客中所描述的那样:
sshguard监控服务器的日志记录活动。当日志显示有人在攻击时,sshguard会作出相应防护措施阻止攻击。
在我们的例子中,我们使用它来保护我们的SSH端口,安装过程非常简单,默认情况下,它将开始检查Ubuntu服务器上的/var/log/auth.log(其中记录了SSH攻击等) )。
在Ubuntu服务器上运行以下命令以安装SSHGuard,它将使用iptables作为系统防火墙。 iptables是一个用于配置和管理内核netfilter模块的程序。
apt-get update apt-get install -y sshguard
当sshguard阻止任何恶意用户(通过阻止其IP地址)时,它将使用sshguard链。准备好sshguard链并确保在检测到新的传入连接时也会触发链,最后重新启动sshguard。
在下面的示例中,sshguard在4次登录尝试失败后开始阻止一次尝试,如果攻击者继续攻击,则会逐渐增加阻止时间。
要查看被阻止的IP地址,请运行以下命令:
通过这个简单的设置,您可以确保您的明智的sshd端口受到保护,以防愚蠢的攻击者试图侵入您的系统。
polkadot验证节点的进入端口
哪个端口,是polkadot验证器所需要的。验证节点需要三个入站端口:
-
30333用于Peer2Peer协议的端口;
-
9933用于RPC;
-
9944用于WebSocket(WS)通信;
理想情况下,验证节点将只公开这三个端口以及允许您登录系统的sshd端口。
polkadot验证节点的出端口
关于保护以及验证程序的出站端口的一些想法。如security.stackexchange线程中所述
https://security.stackexchange.com/questions/24310/why-block-outgoing-network-traffic-with-a-firewall
进入流量阻塞只能阻止未经请求的流量到达您的内部网络。但是,如果您在内部计算机上收到恶意软件(通过运行不受信任的可执行文件或利用漏洞),您仍然会受到攻击。
通过阻止恶意软件连接到命令和控制服务器或清除数据,阻止传出流量有助于限制损坏。
因此,在生产验证程序节点中,这可能被认为是至关重要的,但要注意:
在高度安全环境中,出站过滤的想法似乎是一个自然的过程。然而,这是一项非常庞大和复杂的事情。
为了说明这一点,我通过分析验证节点的通信模式运行了一个快速练习。
为此,我使用了优秀的工具Wire Shark。
“Wireshark是世界上最重要、应用最广泛的网络协议分析仪。它可以让您在微观层面上了解您的网络上发生了什么,并且是许多商业和非盈利企业、政府机构和教育机构的事实(通常是法律上的)标准。”
为了获得WireShark的输入文件,我必须在我的验证器节点上运行tcpdump命令…
并将其加载到Wire Shark中。 正如下面的截图所示。 验证节点使用了大量的出站端口。
预计这将考虑到Validator将使用Peer2Peer通信方案,以便与其他网络中的45个验证节点进行通信。
为了保护出站端口,详细了解底层P2P库是如何工作的,这超出了本文的范围(考虑保护测试节点)。
不过,值得一提的是,支付卡行业数据安全标准只是要求提供信用卡的组织(也是某种验证器)这样做。
PCI DSS要求1.2.1的重点是组织制定政策和程序,将流量限制为业务目的的入站和出站绝对必要的流量。PCI要求1.2.1规定,“将入站和出站流量限制为持卡人数据环境所必需的流量,并明确拒绝所有其他流量。”PCI要求1.2.1的目标是将流量限制为仅必要的、所需的协议、端口或服务,并为所需的ELE提供商业理由。
那么在生产环境中运行Polkadot Validator节点的最低要求是什么。
那么,让我们切换到本文的第二个主题。
提高验证节点的可用性
我正在以7×24方式运行Validator POC-2节点,并试图将削减(由于我的节点不可用)减少到最小。
尽管如此,该进程不时会收到一个终止信号,导致必须启动该进程。
为了自动执行此任务并将削减概率降至最低,我编写了一个小的cron作业脚本,每分钟执行一次。
要触发的脚本(monitorValidator.sh)将检查是否没有运行polkadot进程
要安装crontab,请执行以下命令
如果验证程序进程仍在运行,这将导致每60秒检查一次,否则将重新启动。
在公开报告中,为了协调在Web3空间中工作的团队的协作,一个问题是“为polkadot创建和运行节点集群服务”(https://github.com/w3f/web3 collaboration/issues/43),这将解决可用性问题。
Cosmos比Polkadot更为成熟,它涉及一些主题,其中包括:
-
提供哨兵节点体系结构,这是一个基础设施示例,用于缓解GAIA/COSMOS集线器网络验证程序节点上的DDOS。
“为了缓解这个问题,在云环境中部署了多个分布式节点(哨兵节点)。由于易于扩展,很难对验证程序节点产生影响。新的哨兵节点可以在DDOS攻击期间出现,并且可以使用八卦网络将它们集成到事务流中。”
-
Tendermint HSM密钥管理系统(KMS)
“一种轻量级服务,旨在与GAIAD服务(理想情况下在单独的物理主机上)一起部署,它提供以下功能:
-
对验证程序签名密钥的高可用性访问;
-
即使在验证程序进程受到影响的情况下,也要防止双重签名;
-
硬件安全模块存储验证程序密钥,可在主机损坏后继续使用”
今天就是这样,至少在验证程序冰山一角的表面上,您已经完成了第一步来确保和提高可用性。
在安全性和可用性的背景下,观察polkadot如何随着时间的推移而发展将是很有趣的。
本文转载自公众号:区块链研究实验室-海纳学院的内容将围绕:区块链技术,产品社群,经济模型等全方位的知识体系输出。
欢迎联系作者:csschan1120
-
-
Blender 节点插件开发全流程
2021-06-04 23:24:48文章目录写在前面:blender节点插件的结构NodeTreeNodepropertyNodeSocket准备工作实例创建NodeTree创建组件NodeSocket创建Node创建节点目录并注册上述类其他说明控制台出现乱码插件代码修改并重新安装后没有变化...文章目录
写在前面:
由于网上关于blender自定义节点的文章极少(这也是我特意写本文的原因),本文均为自己摸索和部分参考Blender文档得到,可能会有不严谨和不正确的地方,请观者酌情采纳
目的:借用blender的节点实现自己的可视化节点编程,初步完成基本的输入输出节点
- Blender Version: 2.92
- 完成时间:2021.06.04
- 会使用到的bpy模块:
- import bpy
- from bpy.types import NodeTree
- from bpy.types import NodeSocket
- from bpy.types import Node
- from bpy.utils import register_class
- from bpy.utils import unregister_class
blender节点插件的结构
在正式进入Blender节点插件编写之前,先弄清楚开发流程和包含关系,如下图
白色和蓝色方框中的内容是重点,黑色方框是本次实例要完成的内容,即创建一个和几何节点面板一样的自定义节点面板,并编写几个简单的节点
不愿意看介绍可以直接看实例
NodeTree
如果你用过Blender,Blender中自带了几何节点和材质节点,他们都有单独的面板使用他们,同样的,我们创建的自定义节点也可以拥有自己的独立面板,我们编写的节点程序除了拥有python提供的能力外,同时可以使用Blender提供的API。
Node
如图所示:一个节点可见的部分有5个部分
- 标签
- 图标【可以没有】
- 输出组件(NodeSocket)
- 节点属性(property)
- 输入组件(NodeSocket)
如果把节点分为UI和内部方法两个部分,我们的UI工作也就是这些
property
这个部分来自bpy.props,props全称是property,直译为属性。blender中很多模块都使用到了属性,属性中常用的方法有get()和set(),在需要读取和写入属性值时,会自动调用他们。
这个部分我看了很久,至今也没太明白,主要是创建一个实例后,我怎么通过多种方法访问和修改到它的属性,以及理解他的工作方式。
NodeSocket
直译为节点套接字,我觉得这个不好理解,下文都称为节点组件/NodeSocket。
节点组件是节点的基本组成之一,节点组件内一般都会定义一个property,blender也自带了种类丰富的组件。
准备工作
- 我的电脑中blender的python环境和VScode是分开的,两边的库并不连通。
- 下面的做法并不是必须的,但能极大的帮助插件的开发工作
为了方便开发,需要安装一个python库:使用 pip install fake-bpy-module-2.92 或 进入 https://pypi.org/project/fake-bpy-module-2.92/ 下载,安装在VScode环境中。该库的作用如其名,假的bpy库,只提供代码自动补齐,使用时同样是import bpy。
我推荐用VScode编写,里面有一个Blender Development插件,可以极大的方便插件的编写和调试工作。
实例
所有代码:链接:https://pan.baidu.com/s/1xtUTL4gf46DT5geIUnN9ig
提取码:ldz8创建NodeTree
NodeTree部分的工作量不大,只是注册一个面板,填入必要的信息即可
### NOTE:第一步:创建节点树 ### from bpy.types import NodeTree # 自定义节点编辑面板的信息 class myCustomTree(NodeTree): """一个节点树类型,它将展示在编辑器类型列表中""" bl_idname = 'CustomTreeType' # 面板的id,唯一 bl_label = "My NodeTree" # 面板的标签,用于展示 bl_icon = 'RNA' # 面板的图标,使用Blender自带的图标 # 定义节点时需要这个类 class MyCustomTreeNode: @classmethod def poll(cls, ntree): return ntree.bl_idname == 'CustomTreeType' import nodeitems_utils from nodeitems_utils import NodeCategory, NodeItem # 创建节点目录时需要这个类 class MyNodeCategory(NodeCategory): @classmethod def poll(cls, context): return context.space_data.tree_type == 'CustomTreeType'
创建组件NodeSocket
# Created by Jiacong Zhao @CSDN-奇偕 # XXX The last modification at:2021.06.04 # XXX Topic: 自定义单选组件示例 # XXX Discription: 组件是构成节点的基础 # blender本身自带了NodeSocketInt、NodeSocketFloat、NodeSocketString等组件 import bpy from bpy.types import NodeSocket class Socket_Enum_List(NodeSocket): bl_idname = '_enum_list' bl_label = "enum_list" # 选项列表 my_items = ( # [(identifier, name, description, icon, number), ...] ('C://', "C://", ""), ('D://', "D://", ""), ('E://', "E://", ""), ('F://', "F://", ""), ) # 组件基本信息 myenum: bpy.props.EnumProperty( name="Direction",# 名称 description="一个例子",# 描述 items=my_items,# 可选择的项目 default='C://',# 默认选择 ) def val(self): return self.myenum # 用于绘制在节点框里显示的文本【可选】 def draw(self, context, layout, node, text): if self.is_linked: # 如果被连接,只显示的文本 # text += bpy.props. layout.label(text=text) else: # 没有被连接时,显示文本和选项 layout.prop(self, "myenum", text=text) # 组件颜色【那个小点点】 def draw_color(self, context, node): return (1.0, 0.4, 0.216, 0.5)
创建Node
''' in info s ''' # Created by Jiacong Zhao @CSDN-奇偕 # XXX The last modification at:2021.06.04 # XXX Topic: 打印节点 # XXX Discription: 将得到的任何数据转为字符串并打印,实时刷新 import time import bpy from bpy.types import Node from ..MyCustomTree import * from ..MyCustomSocket import * class PrintNode(Node, MyCustomTreeNode): bl_idname = 'PrintNode' bl_label = "打印" bl_icon = 'CONSOLE' def init(self, context): self.inputs.new('NodeSocketString', "info") def parent_socket(self): return self.inputs[0].links[0].from_socket def draw_buttons(self, context, layout): if self.inputs[0].is_linked: layout.label(text=str(self.parent_socket().default_value)) else: layout.label(text='') def draw_buttons_ext(self, context, layout): ... def draw_label(self): return "打印" # 拓扑图更新时调用 def update(self): print(time.ctime(),end='>>> ') print(str(self.parent_socket().default_value)) # 复制时调用 def copy(self, node): print("Copying from node ", node) # 释放时调用 def free(self): print("Removing node ", self, ", Goodbye!")
创建节点目录并注册上述类
# 插件信息 bl_info = { "name" : "MyCustomAddon", "author" : "QiXie", "description" : "", "blender" : (2, 92, 0), "version" : (0, 0, 1), "location" : "", "warning" : "", "category" : "Generic" } import bpy # View3d面板 from .TestHello import * from .TestMyPanel import * ''' 自定义节点面板 ''' # 节点树--节点组件--节点--节点目录 # from .myNodes import * from .MyCustomTree import * from .MyCustomSocket import Socket_classes from .MyCustomNodes import Node_classes classes = ( Test_OT_Hello, Test_PT_HelloPanel, myCustomTree, ) ### NOTE:创建节点目录 ### node_categories = [ # identifier, label, items list # -->标识符、标签(展示的名称)、项目列表 MyNodeCategory('INPUT', "输入节点", items=[ NodeItem("TextNode"), NodeItem("FileNode"), ]), MyNodeCategory('OUTPUT', "输出节点", items=[ NodeItem("PrintNode"), ]), MyNodeCategory('OTHERNODES', "测试节点", items=[ # --> 节点项可以有额外的设置,可以应用于新的节点 # --> 注意:设置值存储为字符串表达式,因此应该使用repr()将其转换为字符串。 # 由一个节点设置不同的值派生出新节点 # 一个节点有四个属性 # nodetype【类型|必填】 # label【名称】 # settings【设置】:settings[0]【名称】settings[1]【值】 # poll NodeItem("TestNode", label="Node A", settings={ "my_string_prop": repr("文本"), }), NodeItem("TestNode", label="Node B", settings={ "my_string_prop": repr("文本"), }), ]), ] # 类的注册【方法一】 # register, unregister = bpy.utils.register_classes_factory(classes) # 类的注册【方法二】 def register(): from bpy.utils import register_class # 注册 for cls in classes: register_class(cls) # 组件注册 for cls in Socket_classes: register_class(cls) # 节点注册 for cls in Node_classes: register_class(cls) # 节点目录注册 nodeitems_utils.register_node_categories('CUSTOM_NODES', node_categories) def unregister(): nodeitems_utils.unregister_node_categories('CUSTOM_NODES') from bpy.utils import unregister_class # 节点 for cls in Node_classes: unregister_class(cls) # 组件 for cls in Socket_classes: unregister_class(cls) # for cls in reversed(classes): unregister_class(cls) # if __name__ == "__main__": # register()
其他说明
控制台出现乱码
- 路径中包含中文,应更改路径
- 设置了界面语言为中文,应改为English
- 实际上,我建议最好全用英文,即使是下划线,放在最前面有时候也会报错
插件代码修改并重新安装后没有变化
- 旧的插件并没有彻底删除,跳转至Blender放置插件的位置将过期代码删除,并重新尝试安装
- 建议:开发全程使用VS Code的Blender Development插件,调用Blender: Start命令调试插件
查找Blender中的图标
-
打开自带插件icon Viewer,在文本编辑窗口的侧边栏Dev选项中即可查看全部图标,点击即可复制图标名称。
节点 刷新/输出滞后 问题
-
当节点自身拓扑结构发生变化时,Blender会自动调用节点的update方法,因此我们将输入与输出的逻辑关系放在这里
-
当我们改变某节点的父结点的参数时,此时update方法不会被调用,也就是说变化的传递会即刻终止,这在大多数情况下不符合需求,我的解决办法如下:
-
编写自定义NodeSocket,在property of NodeSocket的set方法中,调用NodeSocket父节点的update方法,这样自身参数改变时,输出也会跟着刷新
-
在原有的update方法中运用递归的思想,自身输出刷新后调用子节点的update方法,如下所示
-
for item in self.outputs: for cell in item.links: cell.to_socket.node.update() # 我必须要说明的是,这是一种简单粗暴的方法,当整个节点树比较复杂时,update方法的调用次数是成倍上升的,好的算法应该让每个节点按照一定顺序逐个执行一遍 # 如果你需要掐断这种传递,那么添加一个不含这类代码的节点即可
参考
遇到困难的时候不妨求助以下路径
- 点击打开Blender官方文档 直接看很头痛
- 【Blender Python小白向入门-哔哩哔哩】https://b23.tv/c0UwtY 入门推荐
- 【dog日常:开发blender插件#1-哔哩哔哩】https://b23.tv/zCLcR9 快速了解插件开发
- Blender中的图标 https://blog.csdn.net/qq_42110882/article/details/107151652
- Blender中的模板文件:Text Editor -> Templates
- Github
最终实现效果
目前只是简单做了几个节点,当然,会做几个基本的节点后,后面会快很多。
- Text节点为字符串节点
- File Str节点是打开FilePath下的文件并以指定编码方式输出
- 打印节点顾名思义是将得到的信息打印出来
最终的想法是做一个能处理数据和解决数学问题的节点插件,我认为这种方式去做这些会更为直观
-
转载 解密蓝牙mesh系列 | 第五篇 【好友(Friend)和低功耗节点(LPN)】【友谊(Friendship)参数】【友谊...
2017-09-24 00:56:14所有节点都能够在网络中发送并接收mesh消息,此外还可以选择性地支持一个或多个其他网络特性,如下所列: 中继(Relay)特性: 通过广播承载层接收并重新发送mesh消息、以构建更大规模网络的能力。 ...YD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。SYD8801片上集成了Balun无需阻抗匹配网络、高效率DCDC降压转换器,适合用于可穿戴、物联网设备等。具体可咨询:http://www.sydtek.com/
本文转载于:https://mp.weixin.qq.com/s/gKfLTSu2H0PnAki-8mPCFA
这里只是为了方便学习,绝无抄袭之意!
解密蓝牙mesh系列 | 第五篇
原创2017-09-22 任凯蓝牙技术联盟
蓝牙mesh网络
友谊篇
蓝牙技术联盟亚太区技术项目经理
任凯
低功耗蓝牙(Bluetooth Low Energy)是全球最具节能性的短距离无线通信技术之一。其低功耗的特性广受开发者和消费者赞誉。随着蓝牙mesh网络的推出,开发者可能想知道蓝牙mesh网络是否也被设计为低功耗,是否继承了低功耗蓝牙的这一优点?
答案当然是YES!
蓝牙mesh网络采取了多种优化功耗的措施,特别包括一项称为“friendship” (友谊)的特性。
概述
蓝牙mesh网络中“friendship”(友谊)特性的应用可能非常多样化。一些如照明功能的产品会与主电源(国家电网)相连接,那么相较于照明本身的功耗,蓝牙mesh模块的功耗就可忽略不计。但其他产品,如智能传感器或智能锁,就会在供电方式上功耗受限,这意味着它们需要通过小型电池或能量采集技术来供电。这些产品最有可能利用到蓝牙mesh网络的友谊概念。
如果您阅读过我们蓝牙mesh网络系列之前的文章,那么您就知道节点(Node)是已经启动配置(Provision)并成为mesh网络中一员的设备。节点具有与其产品类型相关的功能,但也可具有与网络本身操作相关的功能并在其中扮演特定角色。而这取决于其所支持的mesh网络特性。所有节点都能够在网络中发送并接收mesh消息,此外还可以选择性地支持一个或多个其他网络特性,如下所列:
-
中继(Relay)特性:通过广播承载层接收并重新发送mesh消息、以构建更大规模网络的能力。
-
代理(Proxy)特性:在GATT和广播承载层之间接收并重新发送mesh消息的能力。
-
低功耗(Low-Power)特性:能够以明显较低的接收端占空比在mesh网络中运行。通过将无线电接收器启用时间最小化可实现节点功耗的降低,只有在绝对必要时才启动接收器。低功耗节点(LPN)通过与好友(friend)节点建立友谊(friendship)关系来实现这一点。
-
好友(Friend)特性:通过存储发往LPN的消息,仅在LPN明确发出请求时才进行转发来帮助LPN运行的能力。
要了解“友谊”是如何帮助LPN降低功耗的,我们可以先从传感器开始:传感器是一个很好的例子,它可以利用“友谊”,并被用作LPN。它们通常将绝大部分时间用于传输数据,且很少需要接收数据。传感器可能只有在温度超出一系列预设的限制时才会发送温度读数,而这种情况每天可能只会发生两次。正是这种不频繁的数据传输才使得此类设备的能耗使用维持在较低水平。
但如果需要根据季节将这些温度限制修改为不同的值,同时需要通过向传感器发送配置消息来实现这些限制的修改呢?传感器若想直接接收此类消息,就需要开启无线电进行收听。大多数时间它什么也接收不到,却在消耗能量。
因此,与好友节点的合作能够使低功耗节点(LPN)规划对无线电的使用,以适当或更低的频率接收消息而无需一直保持收听。低功耗节点会对好友节点进行轮询(Poll),查看是否有新消息(好友节点只会间或地对新消息进行存储)。功耗就是通过上述步骤得到节省的。
好友(Friend)和低功耗节点(LPN)
低功耗节点(LPN)必须与支持“好友”特性的另一节点建立“友谊”(friend)关系,以减少其接收器占空比(Duty Cycle)并节约能耗。图1来自蓝牙mesh配置文件规格,主要描绘了低功耗节点和好友节点之间的关系,具体如下:
浅蓝色:低功耗节点
深灰色:与特定低功耗节点相关联的好友节点
浅灰色:没有与低功耗节点建立关系的好友节点
图 1 - mesh网络的拓扑结构示例
好友节点P与低功耗节点 I、J和K为“友谊”关系。好友节点O与低功耗节点 L和M为“friendship”关系。因此,寻址到节点I、J或 K的消息将被好友节点P存储并转发。寻址至节点L或M的消息将被好友节点 O存储和转发。好友节点的转发仅在低功耗节点轮询好友节点以获得等待传送的消息时才会发生。
友谊(Friendship)参数
低功耗节点需要找到好友节点,与其建立“友谊”关系。所涉及的流程称为“友谊建立”。我们稍后会探讨此流程。在此之前,先介绍一些有关对LPN行为进行管理的关键参数,这些参数被设定于友谊建立过程中。
1. ReceiveDelay是从LPN向好友节点发送请求,到其开始收听响应中间经过的时间。这让好友节点有时间做好响应的准备,并将响应发回。
2. ReceiveWindow 是LPN用于收听响应的时间。图2描述了涉及ReceiveDelay和ReceiveWindow的时序。
图2 - ReceiveDelay和ReceiveWindow时序
3.PollTimeout设定了LPN发送给其好友节点的两个连续请求之间可能经过的最长时间。如果在PollTimeout计时器到时之前,好友节点未能收到LPN的请求,则友谊关系将被终止。
图 3 – PollTimeout时序
“友谊”建立
如果两个人想建立友谊,可能对视一眼就已足够!
但对于蓝牙mesh网络中“友谊”的建立,还需要经过更多的步骤。
-
LPN发布一个“好友请求”(Friend Request)消息。该消息不会被中继,因此只有处于直接无线电范围内的好友节点才能处理该消息。不具有“好友”特性的节点会将消息丢弃。“好友请求” 消息包括LPN的ReceiveDelay、ReceiveWindow和PollTimeout参数。
-
附近的好友节点若支持“好友请求”消息中特定的要求,将准备一个“Friend Offer”消息,并将其发送回LPN。该消息包括各种参数,包括支持的ReceiveWindow大小、可用的消息队列大小、可用的订阅列表(Subscription List)大小、以及由好友节点测量的RSSI值。
-
LPN接收到“Friend Offer”消息时,通过应用一种实施专用的算法来选择合适的好友节点。该算法可能会考虑到各种各样的情况。某些设备可能会优先考虑ReceiveWindow大小,以尽可能减少功耗;而有些设备则可能会更加关注RSSI值,以确保能够与好友节点保持高质量的链路。所采用的精确算法由产品开发者决定。
-
选择好友节点之后,LPN将向好友节点发送一个“Friend Poll”轮询消息。
-
从LPN收到“好友轮询”(Friend Poll)消息后,好友节点会回复一个“Friend Update”更新消息,完成“好友” 建立流程并提供安全参数。此时“友谊”得以建立。
友谊(Friendship)消息传送
友谊建立之后,好友节点将LPN的所有消息存储在“好友队列”(Friend Queue)中,这些消息就是我们所说的“ 被存储的消息 ”。下方的图4描绘的就是好友节点和关联LPN之间的消息交换。
-
当好友节点收到一个寻址到该节点的LPN的消息时,好友节点会缓冲此消息,将其存储在称为“好友队列”的区域中。在图4中,我们可以看到,好友节点为LPN存储了消息1和2。
-
LPN会周期性地启用其收发器(transceiver),并向好友节点发送 “好友轮询” 消息,询问是否存储有任何为其缓冲的消息。
-
好友节点会先将一个被存储的消息发回至LPN作为对“好友轮询”(Friend Poll)的响应。
-
在每次接收到来自好友节点的消息之后,LPN会将继续发送“好友轮询”消息,直到收到一条“MD(MD =更多数据)”字段设置为0的“好友更新”消息为止。这意味着已经没有为LPN缓冲的更多消息了。此时,LPN停止对好友节点的轮询。
图 4 – “友谊”消息传递
安全性
蓝牙mesh中,安全性保障无处不在,“友谊”也如此,它采用两种特殊的安全证书:
-
主安全资料(Master Security Material):由网络密钥(NetKey)派生,可被同一网络中的其他节点使用。使用主安全资料加密的消息可被同一网络中的任何节点解码。
-
好友安全资料(Friend Security Material):由网络密钥(NetKey)、以及由低功耗节点(LPN)和好友节点生成的额外计数器号码派生而来。使用好友安全资料加密的消息只能由处理该消息的好友节点和LPN解码。
LPN和好友节点使用的两种安全资料是怎样的呢?总结如下:
使用好友安全材料加密的相应友谊消息:
-
好友轮询(Friend Poll)
-
好友更新(Friend Update)
-
好友订阅列表(Friend Subscription List)添加/删除/确认好友节点发送至LPN的“被存储的消息”
使用主安全资料加密的相应友谊消息:
-
好友清除(Friend Clear)
-
好友清除确认(Friend Clear Confirm)
从LPN发送至好友节点的消息将根据应用设置,通过主安全资料或好友安全资料进行加密。
“友谊”终止
“友谊”可在某些情况下终止:
-
如果在PollTimeout计时结束之前,好友节点未收到“ 好友轮询”、“好友订阅列表添加”或“好友订阅列表删除”消息,则友谊终止。
-
LPN可以通过将“好友清除”消息发送给好友节点,以启动友谊终止程序,“友谊”就会被好友节点终止。
平台选择小窍门
开发者在选择实施好友和LPN的平台时,应考虑遵循以下指南:
-
RAM容量:可用的RAM容量直接影响一个 好友节点可支持LPN的数量、及其可为相关LPN缓冲多少个消息。
-
LPN:所选MCU和模块的通用功耗性能对于LPN很关键。 此外,从休眠模式到运行模式的唤醒/预热时间会影响LPN的响应速度和延迟。
作为开发者,我像你们一样对蓝牙mesh SDK怀有热切的期望。让我们一同感受蓝牙mesh“ 友谊 ”的魅力吧!
截图:
-
-
MySQL 和 B 树的那些事-爱可生
2021-02-01 14:28:43原标题:MySQL 和 B 树的那些事-爱可生在介绍B树之前,先来看另一棵神奇的树——二叉排序树(Binary Sort Tree),首先它是一棵树,“二叉”这个描述已经很明显了,就是树上的一根树枝开两个叉,于是递归下来就是... -
基于随机游走Random Walk的图节点Node表示
2020-06-01 14:38:50Embedding Nodes ...也就是说,我们希望embedding之后的node vector点乘之后的值(可以理解为未归一化的cosine)接近于原graph中的节点相似度,原图的相似度可以采用是否节点相连,是否有相同的邻居节点等 -
读书笔记——Neo4j实战 使用Neo4jAPI创建节点和关系
2019-11-22 13:49:30创建节点 最开始的两行(程序3-1和程序3-2) 建立了单个user节点, 使用了Java 6(Neo4j 1.9.X) 和Java 7(Neo4j 2.0.X) 的习惯风格。... 如果这是一个已经存在的Neo4j数据库, 就会使用这个数据库。 如果指定的位... -
一文搞懂MySQL索引所有知识点(建议收藏)
2020-10-24 12:19:05这种数据结构我们称为B树,B树是一种多叉平衡查找树,如下图主要特点: B树的节点中存储着多个元素,每个内节点有多个分叉。 节点中的元素包含键值和数据,节点中的键值从大到小排列。也就是说,在所有的节点都储存... -
ROS基本操作 ROS中订阅节点消息测试 ROS下如何订阅任意话题
2021-05-09 11:12:17ROS基本操作 ROS中订阅节点消息测试 ROS下如何订阅任意话题 -
计算机网络的 166 个核心概念
2022-03-17 10:01:43上回我整理了一下计算机网络中所有的关键概念,很多小伙伴觉得很有帮助,但是有一个需要优化的点就是这些概念不知道出自哪里,所以理解起来像是在云里穿梭,一会儿在聊应用层的概念,一会儿又跑到网络层协议了。... -
Jenkinsfile的多分支流水线构建配置
2019-01-21 09:49:43我之前的博客《Jenkins 多分支构建》及《Jenkins 多分支构建中的邮件配置》探索了在多分支构建中Jenkinsfile的配置。然而在我的配置中,根节点为node,但里面却没有使用Jenkinsfile的DSL去声明构建的流程,而是通过... -
第3节 labview多界面切换之:一个子面板显示多个VI
2020-05-03 10:40:13第3节 labview多界面切换之:一个子面板显示多个VI 个人感觉使用较为方便,可实现多种不同界面的切换要求。下面举个例子,使用时可以按照需要修改。 假设需要在一个界面中实现三个不同的图形显示,按下不同选择按钮... -
通俗理解kaggle比赛大杀器xgboost
2018-08-04 14:18:38所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测,然后用某种策略将多个分类器预测的结果集成起来,作为最终预测结果。通俗比喻就是“三个臭皮匠赛过诸葛亮”,或一个公司董事会上的各董事投票决策,... -
7天学会NodeJs(里面讲了很多,最后一个大例子,更是讲了一些工程开发流程,很有收获)
2015-08-19 11:30:10NodeJS基础 ...每一种解析器都是一个运行环境,不但允许JS定义各种数据结构,进行各种计算,还允许JS使用运行环境提供的内置对象和方法做一些事情。例如运行在浏览器中的JS的用途是操作DOM,浏览器就提供了do -
牛逼!Java 从入门到精通,超全汇总版
2021-05-06 19:40:33Java 设计模式Java 进阶Java 并发编程实战Java 并发编程艺术Java 并发编程之美图解Java多线程设计模式JVM深入理解 Java 虚拟机Java 虚拟机规范HotSpot 实战自己动手写 Java 虚拟机MySQLMySQL 基础教程SQL 基础教程... -
(译)一个cocos2d节点不显示的各种原因
2012-09-22 21:52:29举个例子,如果你有三个节点A,B和C,他们的z值A:5、B:-1、C:0,那么B节点的所有的子节点,以及它子节点的子节点都会被首先绘制。接下来是C的所有的子节点,最后才才是A的所有的子节点。如果A的所有的子节的... -
区块链多链架构设计原理
2019-03-18 15:09:16术语介绍 Validator– 主链/子链共识系统的参与者。通过存50000BU到主链中就能成为一名验证者。...当一个委员会被集体提及时,如“该委员会证明X”,这种假定为“该委员会的某个子集包含足够的验... -
Windchill运维常用的节点重置_ 修改流程任务的状态
2019-06-13 09:28:22在系统运维过程中,我们通常会遇到某个工作流任务节点异常,原因多种多样,系统重启导致的呀,队列异常之类的,这个时候需要人工介入修复节点 那么任务节点呢是Windchill的WFASSIGNEDACTIVITY表里面记录的 当你找到... -
SQL 双亲节点查找所有子节点
2016-05-02 21:18:11在 SQL 中常用的是双亲节点法(parent id 表示父节点)。假设当前欲获取某一节点下所有子节点,该怎么做呢?如果使用程序(Java/PHP)递归调用,那么将反复调用数据库,效率之低可想而知。于是我们希望在数据库的... -
2021-2-22:请你说下 CAP 理论并举例
2021-02-22 08:58:03CAP 理论是分布式系统中的一个老生常谈的理论了,最早由 Eric Brewer 在一个讲座中提出。在这个讲座中,在传统 ACID 理论以及当时比较流行但是比较抽象的的设计指导理论 BASE 理论(当时的 BASE 理论还很抽象,直到... -
ES多集群间数据同步
2018-05-16 17:49:02举个例子,现有三个集群分别是:集群A、集群B和集群C,每个集群对应的有三个节点,一共是九个节点;集群A中的node1中的业务数据需要从集群C中node1中某索引中获取(意思是说:集群A需要的一部分数据被分割在其他两个... -
Java多线程面试题,我丝毫不慌
2020-07-28 09:18:51举个例子: 也就是说:在同一个进程内又可以执行多个任务,而这每一个任务我就可以看出是一个线程。 所以说:一个进程会有1个或多个线程的! 1.3进程与线程 于是我们可以总结出: 进程作为资源分配的基本单位 线程... -
不骗你,没读这一篇,你不可能懂二分
2021-03-22 10:34:32上篇文章讲动态规划获得了80k浏览,这次的二分也值得你们一看,这个系列是特别用心准备出书的哦 -
Merkle Patricia Tree (MPT) 树详解
2019-05-17 21:10:58以太坊区块的头部包括一个区块头,一个交易的列表和一个uncle区块的列表。在区块头部包括了交易的hash树根,用来校验交易的列表。在p2p网络上传输的交易是一个简单的列表,它们被组装成一个叫做trie树的特殊数... -
世上最全计算机网络面试整理(附答案),不服来战!!
2021-07-15 17:33:08另外,文末也给出了 PDF 版本,记得给帅地一个赞啊!!! 1、说一说三次握手 当面试官问你为什么需要有三次握手、三次握手的作用、讲讲三次三次握手的时候,我想很多人会这样回答: 首先很多人会先讲下握手的过程: ... -
决策树学习
2020-12-16 16:26:12在这种方法中学习到的函数被表示为一颗决策树,学习得到的决策树也能再被表示为多个if-then规则,以提高可读性。 决策树学习方法对噪声数据有很好的健壮性且能够学习析取表达式。 决策树学习算法有很多,比如ID3、C... -
【Linux网络编程】网络基础知识
2019-11-10 17:25:13它包括用于一个设备能够与另一个设备通信的电缆类型和协议。 2)OSI 参考模型的层次是什么? 有 7 个 OSI 层:物理层,数据链路层,网络层,传输层,会话层,表示层和应用层。 3)什么是骨干网? 骨干网络是集中... -
主宰操作系统的经典算法
2020-07-24 15:22:50进程和线程在调度时候出现过很多算法,这些算法的设计背景是当一个计算机是多道程序设计系统时,会频繁的有很多进程或者线程来同时竞争 CPU 时间片。 那么如何选择合适的进程/线程运行是一项艺术。当两个或两个以上... -
【转】用 Go 构建一个区块链
2019-05-11 17:34:43区块链是 21 世纪最具革命性的技术之一,它仍然处于不断成长的阶段,而且还有很多潜力尚未显现出来。 本质上,区块链只是一个分布式数据库而已。 不过,使它独一无二的是,区块链是一个公开的数据库,而不是一个私人... -
ReentrantLock你了解多少(结合Lock、AQS进行讲解)
2020-04-12 19:39:19这样的设计实现了这种效果:当多个线程争抢资源时,保证只会有一条线程在运行,其他线程都在等待队列里等候安排。打开 AQS 接口看源码,会看到多如牛毛的方法,初识 AQS 如果从这些方法着手,就可以准备去世了,因此...