C4.5决策树生成算法完整版(Python),连续属性的离散化, 缺失样本的添加权重处理, 算法缺陷的修正, 代码等

在这里插入图片描述

C4.5决策树生成算法完整版(Python)

转载请注明出处:©️ Sylvan Ding


ID3算法实验

决策树从一组无次序、无规则的事例中推理出决策树表示的分类规则,采用自顶向下的递归方式,在决策树的内部节点进行属性值的比较并根据不同的属性值判断从该结点向下的分支,在决策树叶结点得到结论。

实验目的

  1. 理解ID3算法原理
  2. 理解C4.5算法原理
  3. 编程实现C4.5算法

决策树生成算法

决策树的生成过程是使用满足划分准则的特征不断地将数据集划分为纯度更高、不确定性更小的子集的过程。

Generate_decision_tree
输入: 训练样本samples,由离散值属性表示;候选属性的集合attribute_list。
输出: 一颗决策树
创建结点N
IF samples都在同一个类C THEN返回N作为叶结点,以类C标记;
IF attribute_list为空 THEN返回N作为叶结点,标记为samples中最普通的类;
选择attribute_list中具有最高信息增益(或增益率)的属性test_attribute;
标记结点N为test_attribute;
FOR each test_attribute中的已知值ai //划分samples由结点N长出一个条件为test_attribute=ai的分支;
设si是samples中test_attribute=ai的样本集合 //一个划分
IF si为空 THEN加上一个树叶,标记为samples中最普通的类;
ELSE 加上一个由Generate_decision_tree(si, attribute_list - test_attribute)返回的结点;

ID3算法原理

  • 决策树中每一个非叶结点对应着一个非类别属性,树枝代表这个属性的值。一个叶结点代表从树根到叶结点之间的路径对应的记录所属的类别属性值。
  • 采用信息增益来选择最佳划分属性。

信息增益计算

ID3总是选择具有最高信息增益(最大熵)的属性作为当前结点的测试属性(test_attribute)。

设S是s个数据样本的集合,假定类标号属性有m个不同值,定义m个不同类Ci(i=1,2,…,m)C_i(i=1,2,\dots,m)Ci(i=1,2,,m)。设sis_isi是类CiC_iCi中的样本数。对一个给定的样本分类所需的期望信息为:

I(s1,s2,…,sm)=−∑i=1mpilog⁡(pi)I(s_1,s2,\dots,s_m) = -\sum_{i=1}^{m}p_i\log(p_i)I(s1,s2,,sm)=i=1mpilog(pi)

其中,pip_ipi是任意样本属于CiC_iCi的概率,pi=sisp_i=\frac{s_i}{s}pi=ssi

设属性A具有v个不同值,则可用属性A将S划分为v个子集,设sijs_{ij}sij是子集SjS_jSj中类CiC_iCi的样本数,则根据A划分子集的熵为:

E(A)=−∑j=1v∑i=1msijsI(s1j,s2j,…,smj)E(A) = -\sum_{j=1}^{v}\frac{\sum_{i=1}^{m}s_{ij}}{s}I(s_{1j}, s_{2j}, \dots, s_{mj})E(A)=j=1vsi=1msijI(s1j,s2j,,smj)

由期望信息和熵值可以得到对应的信息增益值:

Gain(A)=I(s1j,s2j,…,smj)−E(A)Gain(A)=I(s_{1j}, s_{2j}, \dots, s_{mj})-E(A)Gain(A)=I(s1j,s2j,,smj)E(A)

ID3算法分析

优点

ID3算法避免了搜索不包含目标函数的不完整假设空间的主要风险,因为有限个离散值函数可以表示某个决策树。

缺点

无法回溯爬山搜索中常见的风险,如收敛到局部最优,而不是全局最优。ID3算法只能处理离散值的属性。

当特征的取值较多时,根据此特征划分更容易得到纯度高的子集,因此划分之后的熵更低,由于划分前的熵是一定的,所以信息增益更大,ID3偏袒较多值的属性。

C4.5算法

  • 用信息增益率来代替信息增益
  • 合并具有连续属性的值
  • 处理缺少属性值的训练样本

信息增益率

GainRatio(A)=Gain(A)SplitI(A)GainRatio(A)=\frac{Gain(A)}{SplitI(A)}GainRatio(A)=SplitI(A)Gain(A)

其中,

SplitI(A)=−∑j=1vpjlog⁡(pj)SplitI(A)=-\sum_{j=1}^{v}p_j\log(p_j)SplitI(A)=j=1vpjlog(pj)

连续属性的离散化

  • 根据属性的值,对数据集排序;
  • 用不同的阈值将数据集动态划分;
  • 取两个实际值中点作为一个阈值;
  • 取两个划分,所有样本都在这两个划分中;
  • 得到所有可能的阈值和增益率;

对连续属性A进行排序,按阈值将A划分为两部分,一部分落入vjv_jvj对范围内,而另一部分则大于vjv_{j}vj,选择增益率最大的划分所对应的阈值为划分阈值进行属性离散化。注意,当前划分属性为连续属性,则该属性还可以作为其后代的划分属性。新增labelProperties表示属性为连续还是离散。

缺失值处理

选取最优划分属性

有缺失值属性的信息增益为该属性(设该属性为A)下的无缺失值样本占比×\times×无缺失值样本子集的信息增益。

Gain(A)=p×Gain(A~)Gain(A) = p\times Gain(\widetilde{A})Gain(A)=p×Gain(A)

其中,p为A属性下无缺失值样本的占比,即p=∑x∈D~wx∑x∈Dwxp=\frac{\sum_{x\in \widetilde{D}}w_x}{\sum_{x\in D}w_x}p=xDwxxDwxGain(A~)Gain(\widetilde{A})Gain(A)为A属性下无缺失值样本的信息增益,wxw_xwx是样本x的权重,D是所有样本,D~\widetilde{D}D是无缺失样本。

缺失值样本的划分

增加样本权重概念。样本权重的初始值为1,对于无缺失值样本,将其划分到子结点时,权重保持不变。而对于有缺失值样本,在划分时按无缺失值样本在每个分支中所占比重(即对于分支中无缺失值样本数/该属性下无缺失值样本总数)划分到分支中。此时,ID3中所得公式需改写:

Gain(A~)=I(S)−E(A)Gain(\widetilde{A})=I(S)-E(A)Gain(A)=I(S)E(A)

I(S)=−∑i=1mpi~log⁡(pi~)I(S)= -\sum_{i=1}^{m}\widetilde{p_i}\log(\widetilde{p_i})I(S)=i=1mpilog(pi)

E(A)=−∑j=1vrj~I(Sj)E(A)=-\sum_{j=1}^v \widetilde{r_j}I(S^j)E(A)=j=1vrjI(Sj)

Sj=(s1j,s2j,…,smj)S^j=(s_{1j},s_{2j},\dots,s_{mj})Sj=(s1j,s2j,,smj)

S=(s1,s2,…,sm)S=(s_{1},s_{2},\dots,s_{m})S=(s1,s2,,sm)

pi~=∑x∈Di~wx∑x∈D~wx\widetilde{p_i}=\frac{\sum_{x\in \widetilde{D_i}}w_x}{\sum_{x\in \widetilde{D}}w_x}pi=xDwxxDiwx

rj~=∑x∈Dj~wx∑x∈D~wx\widetilde{r_j}=\frac{\sum_{x\in \widetilde{D^j}}w_x}{\sum_{x\in \widetilde{D}}w_x}rj=xDwxxDjwx

pi~\widetilde{p_i}pi是无缺失值样本中第i类所占比例,样本个数按权重计算;rj~\widetilde{r_j}rj是无缺失值样本中属性A上取值为aja_jaj的样本所占比例,样本个数按权重计算。i是样本索引,j是属性索引。

*缺失测试样本的分类

C4.5算法的决策树构造完成后,需要对含缺失值的测试样本进行分类。在为测试样本某属性下的未知值选择分支时,考虑该缺失属性在该分支下的每个叶子结点中属于不同分类的概率,最大概率对于的分类即为所属分类。概率的计算使用该分支下每个叶子结点中不同分类的权值的加权平均。

本实验仅涉及决策树生成算法,故不考虑测试集的分类和决策树剪枝算法。

*C4.5算法的缺陷和修正

当离散属性和连续属性并存时,C4.5算法倾向于选择连续特征作为最佳树分裂点。因此要对最佳分裂点的信息增益进行修正:

Gain(A)=Gain(A)−log⁡(N−1)∣D∣Gain(A) = Gain(A)-\frac{\log{(N-1)}}{\left| D\right|}Gain(A)=Gain(A)Dlog(N1)

其中,N为连续特征可能的分裂点个数,D是样本数目。

此外,C4.5算法的信息增益率偏向取值较少的特征。因此,并不直接选择信息增益率最大的特征,而是在候选特征中找出信息增益高于平均水平的特征,然后在这些特征中再选择信息增益率最高的特征作为最佳划分特征。

本实验编写的决策树生成算法,不考虑上述两种问题的修正。

代码

import copy
import operator
from math import log
from numpy import infNAN = 'Nan'  # 缺失值定义def calcShannonEnt(dataSet: list, labelIndex: int):"""计算对应属性索引下样本的香农熵:param dataSet: 样本:param labelIndex: 属性索引:return: shannonEnt 香农熵"""numEntries = 0  # 样本数(按权重计算)labelCounts = {}# 遍历样本,计算每类的权重for featVec in dataSet:# 样本的属性不为空if featVec[labelIndex] != NAN:weight = featVec[-2]numEntries += weightcurrentLabel = featVec[-1]  # 当前样本的类别# 如果样本类别不在labelCountsif currentLabel not in labelCounts.keys():# 添加该类别,令该类别权重为0labelCounts[currentLabel] = .0# 添加该类别的权重labelCounts[currentLabel] += weightshannonEnt = .0for key in labelCounts:  # 计算信息熵prob = labelCounts[key] / numEntriesshannonEnt -= prob * log(prob, 2)return shannonEntdef splitDataSet(dataSet: list, axis: int, value, AttrType='N'):"""划分数据集:param dataSet: 数据集:param axis: 按第几个特征划分:param value: 划分特征的值:param AttrType: N-离散属性; L-小于等于value值; R-大于value值:return: 对应axis为value(连续情况下则为大于或小于value)的数据集dataSet的子集"""subDataSet = []# N-离散属性if AttrType == 'N':for featVec in dataSet:if featVec[axis] == value:reducedFeatVec = featVec[:axis]reducedFeatVec.extend(featVec[axis + 1:])subDataSet.append(reducedFeatVec)# L-小于等于value值elif AttrType == 'L':for featVec in dataSet:# 样本axis对应属性非空if featVec[axis] != NAN:if featVec[axis] <= value:# 无需减少该特征subDataSet.append(featVec)# R-大于value值elif AttrType == 'R':for featVec in dataSet:if featVec[axis] != NAN:if featVec[axis] > value:# 无需减少该特征subDataSet.append(featVec)else:exit(0)return subDataSetdef calcTotalWeight(dataSet: list, labelIndex: int, isContainNull: bool):"""计算样本对某个特征值的总样本数(按权重计算):param dataSet: 数据集:param labelIndex: 属性索引:param isContainNull: 是否包含空值:return: 样本的总权重"""totalWeight = .0# 遍历样本for featVec in dataSet:# 样本权重weight = featVec[-2]# 不包含空值并且该属性非空if isContainNull is False and featVec[labelIndex] != NAN:# 非空样本树,按权重计算totalWeight += weight# 包含空值if isContainNull is True:# 总样本数totalWeight += weightreturn totalWeightdef splitDataSetWithNull(dataSet: list, axis: int, value, AttrType='N'):"""划分含有缺失值的数据集:param dataSet: 数据集:param axis: 按第几个特征划分:param value: 划分特征的值:param AttrType: N-离散属性; L-小于等于value值; R-大于value值:return: 按value划分的数据集dataSet的子集"""# 属性值未缺失样本子集subDataSet = []# 属性值缺失样本子集nullDataSet = []# 计算非空样本总权重totalWeightV = calcTotalWeight(dataSet, axis, False)# N-离散属性if AttrType == 'N':for featVec in dataSet:if featVec[axis] == value:reducedFeatVec = featVec[:axis]reducedFeatVec.extend(featVec[axis + 1:])subDataSet.append(reducedFeatVec)# 样本该属性值缺失elif featVec[axis] == NAN:reducedNullVec = featVec[:axis]reducedNullVec.extend(featVec[axis + 1:])nullDataSet.append(reducedNullVec)# L-小于等于value值elif AttrType == 'L':for featVec in dataSet:# 样本该属性值未缺失if featVec[axis] != NAN:if value is None or featVec[axis] < value:subDataSet.append(featVec)# 样本该属性值缺失elif featVec[axis] == NAN:nullDataSet.append(featVec)# R-大于value值elif AttrType == 'R':for featVec in dataSet:# 样本该属性值未缺失if featVec[axis] != NAN:if featVec[axis] > value:subDataSet.append(featVec)# 样本该属性值缺失elif featVec[axis] == NAN:nullDataSet.append(featVec)# 计算此分支中非空样本的总权重totalWeightSub = calcTotalWeight(subDataSet, -1, True)# 缺失值样本按权值比例划分到分支中for nullVec in nullDataSet:nullVec[-2] = nullVec[-2] * totalWeightSub / totalWeightVsubDataSet.append(nullVec)return subDataSetdef calcGainRatio(dataSet: list, labelIndex: int, labelType: bool):"""计算信息增益率,返回信息增益率和连续属性的划分点:param dataSet: 数据集:param labelIndex: 属性索引:param labelType: 属性类型,0为离散,1为连续:return: 信息增益率和连续属性的划分点"""# 计算根节点的信息熵baseE = calcShannonEnt(dataSet, labelIndex)# 对应labelIndex的特征值向量featVec = [row[labelIndex] for row in dataSet]# featVec值的种类uniqueVals = set(featVec)newE = .0  # 新信息熵bestPivotValue = None  # 最佳划分属性IV = .0  # 该变量取自西瓜书# 总样本权重totalWeight = calcTotalWeight(dataSet, labelIndex, True)# 非空样本权重totalWeightV = calcTotalWeight(dataSet, labelIndex, False)# 对离散的特征if labelType == 0:# 按属性值划分数据集,计算各子集的信息熵for value in uniqueVals:# 划分数据集subDataSet = splitDataSet(dataSet, labelIndex, value)# 计算子集总权重totalWeightSub = calcTotalWeight(subDataSet, labelIndex, True)# 过滤空属性if value != NAN:prob = totalWeightSub / totalWeightVnewE += prob * calcShannonEnt(subDataSet, labelIndex)prob1 = totalWeightSub / totalWeightIV -= prob1 * log(prob1, 2)# 对连续的特征else:uniqueValsList = list(uniqueVals)# 过滤空属性if NAN in uniqueValsList:uniqueValsList.remove(NAN)# 计算空值样本的总权重,用于计算IVdataSetNull = splitDataSet(dataSet, labelIndex, NAN)totalWeightN = calcTotalWeight(dataSetNull, labelIndex, True)probNull = totalWeightN / totalWeightif probNull > 0:IV += -1 * probNull * log(probNull, 2)# 属性值排序sortedUniqueVals = sorted(uniqueValsList)minEntropy = inf # 定义最小熵# 如果UniqueVals只有一个值,则说明只有左子集,没有右子集if len(sortedUniqueVals) == 1:totalWeightL = calcTotalWeight(dataSet, labelIndex, True)probL = totalWeightL / totalWeightVminEntropy = probL * calcShannonEnt(dataSet, labelIndex)IV = -1 * probL * log(probL, 2)# 如果UniqueVals只有多个值,则计算划分点else:for j in range(len(sortedUniqueVals) - 1):pivotValue = (sortedUniqueVals[j] + sortedUniqueVals[j + 1]) / 2# 对每个划分点,划分得左右两子集dataSetL = splitDataSet(dataSet, labelIndex, pivotValue, 'L')dataSetR = splitDataSet(dataSet, labelIndex, pivotValue, 'R')# 对每个划分点,计算左右两侧总权重totalWeightL = calcTotalWeight(dataSetL, labelIndex, True)totalWeightR = calcTotalWeight(dataSetR, labelIndex, True)probL = totalWeightL / totalWeightVprobR = totalWeightR / totalWeightVEnt = probL * calcShannonEnt(dataSetL, labelIndex) + probR * calcShannonEnt(dataSetR, labelIndex)# 取最小的信息熵if Ent < minEntropy:minEntropy = EntbestPivotValue = pivotValueprobL1 = totalWeightL / totalWeightprobR1 = totalWeightR / totalWeightIV += -1 * (probL1 * log(probL1, 2) + probR1 * log(probR1, 2))newE = minEntropygain = totalWeightV / totalWeight * (baseE - newE)# 避免IV为0(属性只有一个值的情况下)if IV == 0.0:IV = 0.0000000001gainRatio = gain / IVreturn gainRatio, bestPivotValuedef chooseBestFeatureToSplit(dataSet: list, labelProps: list):"""选择最佳数据集划分方式:param dataSet: 数据集:param labelProps: 属性类型,0离散,1连续:return: 最佳划分属性的索引和连续属性的最佳划分值"""numFeatures = len(labelProps)  # 属性数bestGainRatio = -inf  # 最大信息增益bestFeature = -1  # 最优划分属性索引bestPivotValue = None  # 连续属性的最佳划分值for featureI in range(numFeatures):  # 对每个特征循环gainRatio, bestPivotValuei = calcGainRatio(dataSet, featureI, labelProps[featureI])# 取信息益率最大的特征if gainRatio > bestGainRatio:bestGainRatio = gainRatiobestFeature = featureIbestPivotValue = bestPivotValueireturn bestFeature, bestPivotValuedef majorityCnt(classList: list, weightList: list):"""返回出现次数最多的类别(按权重计):param classList: 类别:param weightList: 权重:return: 出现次数最多的类别"""classCount = {}# 计算classCountfor cls, wei in zip(classList, weightList):if cls not in classCount.keys():classCount[cls] = .0classCount[cls] += wei# 排序sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)# 仅剩一个类别if len(sortedClassCount) == 1:return sortedClassCount[0][0], sortedClassCount[0][1]# 剩余多个类别,返回出现次数最多的类别return sortedClassCount[0][0], sortedClassCount[0][1]def isSame(dataSet: list):"""比较样本特征是否相同:param dataSet: 数据集:return: 相同True,否则False"""for j in range(len(dataSet[0])-2):for i in range(1, len(dataSet)):if not dataSet[i][j] == dataSet[0][j]:return Falsereturn Truedef createTree(dataSet: list, labels: list, labelProps: list):"""创建决策树(Decision Tree):param dataSet: 数据集:param labels: 属性集:param labelProps: 属性类型,0离散,1连续:return: 决策树"""classList = [sample[-1] for sample in dataSet]  # 类别向量weightList = [sample[-2] for sample in dataSet]  # 权重向量# 如果只剩一个类别,返回并退出if classList.count(classList[0]) == len(classList):totalWeight = calcTotalWeight(dataSet, 0, True)return classList[0], totalWeight# 如果所有特征都遍历完了,返回出现次数最多的类别,并退出if len(dataSet[0]) == 1:return majorityCnt(classList, weightList)# 如果剩余样本特征相同,返回出现次数最多的类别,并退出if isSame(copy.copy(dataSet)):return majorityCnt(classList, weightList)# 计算最优分类特征的索引,若为连续属性,则还返回连续属性的最优划分点bestFeat, bestPivotValue = chooseBestFeatureToSplit(dataSet, labelProps)# 对离散的特征if labelProps[bestFeat] == 0:bestFeatLabel = labels[bestFeat]myTree = {bestFeatLabel: {}}labelsNew = copy.copy(labels)labelPropertyNew = copy.copy(labelProps)# 已经选择的离散特征不再参与分类del (labelsNew[bestFeat])del (labelPropertyNew[bestFeat])featValues = [sample[bestFeat] for sample in dataSet]# 最佳花划分属性包含的所有值uniqueValue = set(featValues)# 删去缺失值uniqueValue.discard(NAN)# 遍历每个属性值,递归构建树for value in uniqueValue:subLabels = labelsNew[:]subLabelProperty = labelPropertyNew[:]myTree[bestFeatLabel][value] = createTree(splitDataSetWithNull(dataSet, bestFeat, value),subLabels, subLabelProperty)# 对连续特征,不删除该特征,分别构建左子树和右子树else:bestFeatLabel = labels[bestFeat] + '<' + str(bestPivotValue)myTree = {bestFeatLabel: {}}subLabels = labels[:]subLabelProperty = labelProps[:]# 构建左子树valueLeft = 'Y'myTree[bestFeatLabel][valueLeft] = createTree(splitDataSetWithNull(dataSet, bestFeat, bestPivotValue, 'L'),subLabels, subLabelProperty)# 构建右子树valueRight = 'N'myTree[bestFeatLabel][valueRight] = createTree(splitDataSetWithNull(dataSet, bestFeat, bestPivotValue, 'R'),subLabels, subLabelProperty)return myTreeif __name__ == '__main__':# 读取数据文件fr = open(r'data.csv')data = [row.strip().split(',') for row in fr.readlines()]labels = data[0][0:-1]  # labels:属性dataset = data[1:]  # dataset:数据集(初始样本)labelProperties = [0, 1, 0]  # labelProperties:属性标识,0为离散,1为连续# 样本权重初始化for row in dataset:row.insert(-1, 1.0)# 按labelProperties连续化离散属性for row in dataset:for i, lp in enumerate(labelProperties):# 若标识为连续属性,则转化为float型if lp:row[i] = float(row[i])# C4.5算法生成决策树trees = createTree(copy.copy(dataset), copy.copy(labels), copy.copy(labelProperties))print(trees)

Python3.6

结果验证

在data.csv数据集上运行上述代码,得到结果如下:

{'天气': {'多云': ('玩', 3.230769230769231), '晴': {'湿度<77.5': {'Y': ('玩', 2.0), 'N': {'有雨?': {'有': ('不玩', 1.0), '无': ('不玩', 2.0)}}}}, '雨': {'有雨?': {'有': {'湿度<85.0': {'Y': ('不玩', 2.0), 'N': ('玩', 0.38461538461538464)}}, '无': ('玩', 3.0)}}}}  // (结果, 权重)

附录(data.csv)

天气湿度有雨?去玩?
70
90不玩
85不玩
95不玩
70
Nan90
多云78
多云65
多云75
80不玩
70不玩
80
80
96

参考

  1. 数据挖掘原理与算法(第3版)
  2. 《机器学习》周志华
  3. 决策树–信息增益,信息增益比,Geni指数的理解
  4. 机器学习笔记(5)——C4.5决策树中的连续值处理和Python实现
  5. 机器学习笔记(7)——C4.5决策树中的缺失值处理

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

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

相关文章

unittest单元测试笔记

单元测试 unittest单元测试是基于java的JUnit思想框架开发出来的测试框架 import unittest import HTMLTestRunner class Mytest1(unittest.TestCase):def test_a(self):#用例必须已test开头self.assertEqual(1,1,msg错误提示信息,如果校验失败,出现这个)print(a)def test_c(s…

缅怀袁隆平院士:一颗稻谷里的爱国情怀

来源&#xff1a;科学网5月22日&#xff0c;《中国科学报》从中国工程院获悉&#xff0c;“共和国勋章”获得者、中国工程院院士袁隆平&#xff0c;因多器官功能衰竭&#xff0c;于2021年5月22日13时07分在长沙逝世&#xff0c;享年91岁。袁隆平对于国人来说&#xff0c;袁隆平…

k-Means——经典聚类算法实验(Matlab实现)

聚类算法—k-Means实验 k-平均&#xff08;k-Means&#xff09;&#xff0c;也被称为k-均值&#xff0c;是一种得到最广泛使用的聚类算法[1]. k-Means算法以k为参数&#xff0c;把n个对象分为k个簇&#xff0c;使得簇内具有较高的相似度。 实验目的 了解常用聚类算法及其优缺…

这5个数学猜想最早在30年前提出,如今AI证明它们都错了

来源&#xff1a;AI科技评论编译&#xff1a;琰琰编辑&#xff1a;青暮近日&#xff0c;以色列特拉维夫大学研究团队在预印论文库提交了一篇名为“Constructions in combinatorics via neural networks“的论文&#xff0c;在这篇论文中&#xff0c;研究人员通过机器学习算法证…

Java AQS 核心数据结构-CLH 锁及优化

Java AQS 核心数据结构-CLH 锁 什么是CLH锁 CLH 锁是对自旋锁的一种改进&#xff0c;有效的解决了以上的两个缺点。 第一个是锁饥饿问题。在锁竞争激烈的情况下&#xff0c;可能存在一个线程一直被其他线程”插队“而一直获取不到锁的情况。第二是性能问题。在实际的多处理上…

M/M/m排队模型 (单队列多服务台并联服务模型)数学建模: 基于生灭过程的理论计算和基于事件推进的Matlab模拟仿真思路

M/M/m排队模型 (单队列多服务台并联服务模型) 数学建模: 基于生灭过程的理论计算和基于事件推进的Matlab模拟仿真思路 原创文章&#xff0c;转载文章请注明出处&#xff1a;©️Sylvan Ding &#x1f389;&#x1f389;&#x1f389; 摘要 本文研究M/M/m单队列多服务台并…

不要排斥中文注释

项目的代码注释&#xff0c;我们并不限定只能使用英文&#xff0c;对某些对较为复杂算法的解释&#xff0c;用英文会带来理解上的问题&#xff0c;用中文注释更易理解&#xff0c;一般简单易懂的可以用英文&#xff0c;注释最重要的是能够看懂&#xff0c;看不懂&#xff0c;用…

用物理学来为生命技术及制度的演化找出规律-读《为什么世界不会失控》

来源&#xff1a;混沌巡洋舰物理学的规律是最底层的最永恒的&#xff0c;但能够对抗变化&#xff0c;维持自身结构的活系统&#xff0c;其规律则是最丰富的。“The physics of life”这本书&#xff0c;则是用能量的产生和耗散为视角&#xff0c;解释一切活系统&#xff0c;包括…

js正则检测输入内容为数字,包括负数,整数,浮点数,亲测可用.JS检测整数,js检测浮点数,js检测负数,js检测数字,js限制输入框只输入数字,解决H5 number类型只能输入正数问题.

JS 正则实现数字检测和限制输入&#xff0c;包括整数、浮点数、负数&#xff08;亲测可用&#xff09; 网上搜了一下&#xff0c;居然可以直接拿来用的很少&#xff0c;要么就是只能检测正整数、要么是只能检测浮点数&#xff0c;总之很多都不适合&#xff0c;而H5提供的type&q…

collection 多态 会自动转型为子类 继承多态需要显示转型

转载于:https://www.cnblogs.com/classmethond/p/10057670.html

深入地下,实地探访!不用人挖煤的智能煤矿长什么样?

来源&#xff1a;脑极体未来智能实验室的主要工作包括&#xff1a;建立AI智能系统智商评测体系&#xff0c;开展世界人工智能智商评测&#xff1b;开展互联网&#xff08;城市&#xff09;云脑研究计划&#xff0c;构建互联网&#xff08;城市&#xff09;云脑技术和企业图谱&a…

HanLP中文分词、人名识别、地名识别

HanLP中文分词、人名识别、地名识别 实验目的 从网上下载和安装HanLP自然语言处理包;熟悉HanLP自然语言处理包的基本功能;利用网络爬虫获取的信息&#xff0c;调用HanLP的API&#xff0c;进行中文分词、人名识别、地名识别. 研究背景 随着互联网和信息技术的快速发展&#…

这些行业,将率先落地AI芯片 | 星前沿

来源&#xff1a;联想之星广义上&#xff0c;所有面向AI应用的芯片都可以称为AI芯片。目前一般认为是针对AI算法做了特殊加速设计的芯片。现阶段&#xff0c;这些人工智能算法一般以深度学习算法为主&#xff0c;也可以包括其他浅层机器学习算法。人工智能芯片分类一般有按技术…

[NOI2007]社交网络

题目描述 在社交网络&#xff08;social network&#xff09;的研究中&#xff0c;我们常常使用图论概念去解释一些社会现象。不妨看这样的一个问题。在一个社交圈子里有n个人&#xff0c;人与人之间有不同程度的关系。我 们将这个关系网络对应到一个n个结点的无向图上&#xf…

vueJs的简单入门以及基础语法

vue的api vue官网API 1基础语法 1-1基本数据绑定 <div id"app">{{ msg }} </div> //script new Vue({el:"#app",//代表vue的范围data:{msg:hello Vue //数据} }) 在这个例子中我们可以进行赋值 var app new Vue(...); app.msg 初探vue; //那…

应用数学的强大威力

来源&#xff1a;数学中国 应用数学思想是科研当中非常重要的一种思维方式以及研究方法。今天我们就借助戴世强教授的三篇有关应用数学的文章来详细了解一下这些问题&#xff1a;什么是“应用数学思维”&#xff1f;我们如何在研究中使用应用数学思维&#xff1f;应用数学思维…

正则化实现降噪,分别使用最小二乘、定步长梯度下降和回溯法的梯度下降求解最优解

正则化实现降噪&#xff0c;分别使用最小二乘、定步长梯度下降和回溯法的梯度下降求解最优解 原创文章&#xff01;转载需注明来源&#xff1a;©️ Sylvan Ding’s Blog ❤️ 实验目的 参考 INTRODUCTION TO NONELINEAR OPTIMIZATION. Amir Beck. 2014 的 3.4 Denoising …

双向 RNN

1.基本理论 双向 RNN 结合时间上从序列起点开始移动的 RNN 和另一个时间上从序列末尾开始移动的 RNN 2.逻辑图 其中 h (t) 代表通过时间向前移动的子 RNN 的状态&#xff0c;g (t) 代表通过时间向后移动的子 RNN 的状态 允许输出单元 o (t) 能够计算同时依赖于过去和未来且对时…

Hadoop伪分布式配置和搭建,hadoop单机安装,wordcount实例测试,hadoop安装java目录怎么找,问题及问题解决方法

Hadoop伪分布式配置和搭建&#xff0c;hadoop单机安装&#xff0c;wordcount实例测试&#xff0c;hadoop安装java目录怎么找&#xff0c;问题及问题解决方法 环境说明 系统&#xff1a;ubuntu18.04 主机名&#xff1a;test1 用户名&#xff1a;sylvan hadoop单机安装 换源操作…

AI时代竟有智能化鸿沟,具备哪些条件才能跨过?

来源&#xff1a;CSDN移动互联网“早古”时期&#xff0c;普通人因为收入差距问题而无法做到人手一部智能手机&#xff0c;从而导致数字鸿沟。同样&#xff0c;在当前这个AI&#xff0c;也就是人工智能扮演越来越关键作用的时代&#xff0c;企业也站在了类似的抉择交接线上——…