目录

1、决策树

2、决策树的构造

3、决策树的可视化

4、测试和存储决策树


1、决策树

你是否玩过二十个问题的游戏,游戏的规则很简单:参与游戏的一方在脑海里想某个事物,其他参与者向他提问题,只允许提20个问题,问题的答案也只能用对或错回答。问问题的人通过推断分解,逐步缩小待猜测事物的范围。决策树的工作原理与20个问题类似,用户输人一系列数据,然后给出游戏的答案。

我们经常使用决策树处理分类问题,近来的调查表明决策树也是最经常使用的数据挖掘算法R。它之所以如此流行,一个很重要的原因就是使用者基本上不用了解机器学习算法,也不用深究它是如何工作的。

本文构造的决策树算法能够读取数据集合,构建类似于图下的决策树。

①优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。

②缺点:可能会产生过度匹配问题。

③适用数据类型:数值型和标称型。

④决策树的一般流程:

(1)决策树的一般流程

(2)准备数据;树构造算法只适用于标称型数据,因此数值型数据必须离散化。

(3)分析数据:可以使用任何方法,构造树完成之后我们应该检查图形是否符合预期。

(4)训练算法:构造树的数据结构。

(5)测试算法:使用经验树计算错误率。

(6)使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据
的内在含义。

2、决策树的构造

在构造决策树时,我们需要解决的第一个问题就是,当前数据集上哪个特征在划分数据分类时起决定性作用。为了找到决定性的特征,划分出最好的结果,我们必须评估每个特征。完成测试之后,原始数据集就被划分为几个数据子集。这些数据子集会分布在第一个决策点的所有分支上。如果某个分支下的数据属于同一类型,则当前无需阅读的垃圾邮件已经正确地划分数据分类,无需进一步对数据集进行分割。如果数据子集内的数据不属于同一类型,则需要重复划分数据子集的过程。如何划分数据子集的算法和划分原始数据集的方法相同,直到所有具有相同类型的数据均在一个数据子集内。

下表的数据包含5个海洋动物,特征包括:不浮出水面是否可以生存,以及是否有脚践。我们可以将这些动物分成两类:鱼类和非鱼类。现在我们想要决定依据第一个特征还是第二个特征划分数据。在回答这个问题之前,我们必须采用量化的方法判断如何划分数据。

划分数据集的大原则是:将无序的数据变得更加有序。我们可以使用多种方法划分数据集,但是每种方法都有各自的优缺点。组织杂乱无章数据的一种方法就是使用信息论度量信息,信息论是量化处理信息的分支科学。我们可以在划分数据之前使用信息论量化度量信息的内容。

在划分数据集之前之后信息发生的变化称为信息增益,知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择
       
        在可以评测哪种数据划分方式是最好的数据划分之前,我们必须学习如何计算信息增益。集合信息的度量方式称为香农嫡或者简称为嫡,这个名字来源于信息论之父克劳德·香农。

为了计算嫡,我们需要计算所有类别所有可能值包含的信息期望值,通过下面的公式得到:

1、计算给定数据集的熵

先利用createDataSet()函数得到简单鱼的鉴定数据集。

#创建数据
def createDataSet():dataSet = [[1,1,1],[1,1,1],[1,0,0],[0,1,0],[0,1,0]]#最后一列数据1代表为鱼类,0代表非鱼类labels = ['no surfacing','flippers']return dataSet,labels

首先,计算数据集中实例的总数。我们也可以在需要时再计算这个值,但是由于代码中多次用到这个值,为了提高代码效率,我们显式地声明一个变量保存实例总数。然后,创建一个数据字典,它的键值是最后一列的数值。如果当前键值不存在,则扩展字典并将当前键值加人字典。每个键值都记录了当前类别出现的次数。最后,使用所有类标签的发生频率计算类别出现的概率。我们将用这个概率计算香农嫡,统计所有类标签发生的次数。

#计算给定数据的香农熵
def calShannonEnt(dataSet):numEntries = len(dataSet)#返回数据集的行数labelCounts = {}#保存每个标签(Label)出现次数的字典for featVec in dataSet:#对每组特征向量进行统计currentLabel = featVec[-1]if currentLabel not in labelCounts.keys(): #如果标签没有放入统计次数的字典,添加进去labelCounts[currentLabel] = 0labelCounts[currentLabel]+=1shannonEnt = 0.0for key in labelCounts:prob = float(labelCounts[key])/numEntries#选择该标签(Label)的概率shannonEnt = shannonEnt - prob*log(prob,2)#香农熵return shannonEnt

2、划分数据集

我们学习了如何度量数据集的无序程度,分类算法除了需要测量信息嫡,还需要划分数据集,度量花费数据集的嫡,以便判断当前是否正确地划分了数据集。我们将对每个特征划分数据集的结果计算一次信息嫡,然后判断按照哪个特征划分数据集是最好的划分方式。

#划分数据集
#我们将对每个特征划分数据集的结果计算一次信息熵,然后判断按照那个特征划分数据集是最好的划分方式
def splitDataSet(dataSet,axis,value):retDataSet = []#创建返回的数据集列表for featVec in dataSet:if featVec[axis] ==value:reduceFeatVec = featVec[:axis] #去掉axis特征reduceFeatVec.extend(featVec[axis+1:])#将符合条件的添加到返回的数据集retDataSet.append(reduceFeatVec)return retDataSet#返回划分后的数据集

我们输出检查一下:

dataSet,labels = createDataSet()#创建数据
ans1 = splitDataSet(dataSet,0,1)
print(ans1)

可以得到输出的结果为:

在开始划分数据集之前,我们需要计算整个数据集的原始香农嫡,我们保存最初的无序度量值,用于与划分完之后的数据集计算的嫡值进行比较。第1个for循环遍历数据集中的所有特征。使用列表推导(List Comprehension)来创建新的列表,将数据集中所有第i个特征值或者所有可能存在的值写入这个新list中。然后使用Python语言原生的集合(set)数据类型。集合数据类型与列表类型相似,不同之处仅在于集合类型中的每个值互不相同。从列表中创建集合是Python语言得到列表中唯一元素值的最快方法。

遍历当前特征中的所有唯一属性值,对每个特征划分一次数据集,然后计算数据集的新嫡值,并对所有唯一特征值得到的嫡求和。信息增益是嫡的减少或者是数据无序度的减少,大家肯定对于将嫡用于度量数据无序度的减少更容易理解。最后,比较所有特征中的信息增益,返回最好特征划分的索引值。

#选择最好的数据集划分方式
def chooseBestFeatureToSplit(dataSet):numFeature = len(dataSet[0])-1#特征数量,-1是因为最后一个是类别baseEntopy = calShannonEnt(dataSet)#计算数据集的香农熵bestInfoGain = 0.0#信息增益bestFeature = -1 #最优特征的索引值for i in range(numFeature):#获取dataSet的第i个所有特征featList = [example[i] for example in dataSet]uniqueVals = set(featList) #创建set集合{},元素不可重复newEntropy = 0.0#计算每种划分方式的信息熵for value in uniqueVals:subDataSet = splitDataSet(dataSet,i,value)#subDataSet划分后的子集prob = len(subDataSet)/float(len(dataSet)) #计算子集的概率newEntropy += prob*calShannonEnt(subDataSet)InfoGain = baseEntopy -newEntropy #信息增益if (bestInfoGain<InfoGain):bestInfoGain = InfoGainbestFeature = ireturn bestFeature

输出检查一下:

dataSet,labels = createDataSet()#创建数据
# ans1 = splitDataSet(dataSet,0,1)
bestFeature = chooseBestFeatureToSplit(dataSet)
print(bestFeature)

得到的输出结果为:

代码运行结果告诉我们,第0个特征是最好的用于划分数据集的特征。结果是否正确呢?这个结果又有什么实际意义呢?数据集中的数据来源于表3-1,如果我们按照第一个特征属性划分数据,也就是说第一个特征是1的放在一个组,第一个特征是0的放在另一个组,数据一致性如何?按照上述的方法划分数据集,第一个特征为1的海洋生物分组将有两个属于鱼类,一个属于非鱼类;另一个分组则全部属于非鱼类。如果按照第二个特征分组,结果又是怎么样呢?第一个海洋动物分组将有两个属于鱼类,两个属于非鱼类;另一个分组则只有一个非鱼类。

3、递归构建决策树

目前我们已经学习了从数据集构造决策树算法所需要的子功能模块,其工作原理如下:得到原始数据集,然后基于最好的属性值划分数据集,由于特征值可能多于两个,因此可能存在大于两个分支的数据集划分。第一次划分之后,数据将被向下传递到树分支的下一个节点,在这个节点上,我们可以再次划分数据。因此我们可以采用递归的原则处理数据集。

递归结束的条件是:程序遍历完所有划分数据集的属性,或者每个分支下的所有实例都具有相同的分类。如果所有实例具有相同的分类,则得到一个叶子节点或者终止块。任何到达叶子节点的数据必然属于叶子节点的分类。

第一个结束条件使得算法可以终止,我们甚至可以设置算法可以划分的最大分组数目。

#出现次数最多的分类名称
def majorityCnt(classList):classCount = {}for vote in  classList:if vote not in classCount.keys():classCount[vote] = 0classCount[vote]+=1sortedClassCount = sorted(classCount.items(),key = operator.itemgetter(1),reverse = True)return sortedClassCount[0][0]

递归函数的第一个停止条件是所有的类标签完全相同,则直接返回该类标签。递归函数的第二个停止条件是使用完了所有特征,仍然不能将数据集划分成仅包含唯一类别的分组。由于第二个条件无法简单地返回唯一的类标签,这里使用函数挑选出现次数最多的类别作为返回值。

#创建树
def createTree(dataSet,labels):classList = [example[-1] for example in dataSet]if classList.count(classList[0])==len(classList): #如果类别完全相同则停止继续划分return classList[0]if len(dataSet[0])==1:   #遍历完所有特征时返回出现次数最多的类标签return majorityCnt(classList)bestFeat = chooseBestFeatureToSplit(dataSet)   #选择最优特征bestFeatLabel = labels[bestFeat]   #最优特征的标签myTree = {bestFeatLabel:{}}   #根据最优特征的标签生成树del (labels[bestFeat])   #删除已经使用特征标签featValues = [example[bestFeat] for example in dataSet]  #得到训练集中所有最优特征的属性值uniqueVals = set(featValues)     #去掉重复的属性值for valus in uniqueVals:   #遍历特征,创建决策树。subLabels = labels[:]   #复制类标签myTree[bestFeatLabel][valus] = createTree(splitDataSet(dataSet,bestFeat,valus),subLabels)return myTree
dataSet,labels = createDataSet()#创建数据
myTree = createTree(dataSet,labels)
print(myTree)

构造的树为:

至此,我们的决策树已经构造完成了,接下来讲的是怎么样将决策树进行可视化处理。

3、决策树的可视化

本节我们将使用Matplotlib库创建树形图。决策树的主要优点就是直观易于理解,如果不能将其直观地显示出来,就无法发挥其优势。Python并没有提供绘制树的工具,因此我们必须自己绘制树形图。可视化这里我就不做过多的讲解了,大家可以直接看代码部分。

import matplotlib.pyplot as plt
import operator#定义文本框和箭头格式
decisionNode = dict(boxstyle = 'sawtooth',fc = '0.8')
leafNode = dict(boxstyle = 'round4',fc = '0.8')
arrow_args = dict(arrowstyle = '<-')#绘制带箭头的注解
def plotNode(nodeTxt,centerPt,parentPt,nodeType):createPlot.ax1.annotate(nodeTxt, xy=parentPt,  xycoords='axes fraction',xytext=centerPt, textcoords='axes fraction',va="center", ha="center", bbox=nodeType, arrowprops=arrow_args )def createPlot(inTree):fig = plt.figure(1,facecolor='white')fig.clf()axprops = dict(xticks=[], yticks=[])createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)    #no ticksplotTree.totalW = float(getNumLeafs(inTree))plotTree.totalD = float(getTreeDepth(inTree))plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0;plotTree(inTree, (0.5,1.0), '')plt.show()#获取叶节点的数目
def getNumLeafs(myTree):numLeafs = 0firstStr = list(myTree.keys())[0]   #python3中myTree.keys()返回的是dict_keys,不是list,所以不能使用myTree.keys()[0]的方法获取结点属性,可以使用secondDict = myTree[firstStr]   #获取下一组字典for key in secondDict.keys():if type(secondDict[key]).__name__=='dict':  #测试节点的数据类型是否为字典numLeafs += getNumLeafs(secondDict[key])else:numLeafs+=1return numLeafs#获取树的层数
def getTreeDepth(myTree):maxDepth = 0firstStr = list(myTree.keys())[0]secondDict = myTree[firstStr]for key in secondDict.keys():if type(secondDict[key]).__name__=='dict':thisDepth =1 + getTreeDepth(secondDict[key])else:thisDepth =1if thisDepth >maxDepth:maxDepth = thisDepthreturn maxDepthdef retrieveTree(i):listOfTrees =[{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},{'no surfacing': {0: 'no', 1: {'flippers': {0: {'head': {0: 'no', 1: 'yes'}}, 1: 'no'}}}}]return listOfTrees[i]#在父子节点之间填充文本信息
def plotMidText(cntrPt,parentPt,txtString):xMid = (parentPt[0]-cntrPt[0])/2.0 +cntrPt[0]#计算节点yMid = (parentPt[1]-cntrPt[1])/2.0 +cntrPt[1]createPlot.ax1.text(xMid,yMid,txtString)def plotTree(myTree,parentPt,nodeTree):#计算宽与高numLeafs = getNumLeafs(myTree)depth = getTreeDepth(myTree)firstStr = list(myTree.keys())[0]cntrPt = (plotTree.xOff+(1.0+float(numLeafs))/2.0/plotTree.totalW,plotTree.yOff)plotMidText(cntrPt,parentPt,nodeTree)plotNode(firstStr, cntrPt, parentPt, decisionNode)secondDict = myTree[firstStr]plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalDfor key in secondDict.keys():if type(secondDict[key]).__name__=='dict':plotTree(secondDict[key],cntrPt,str(key))else:plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalWplotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalDTree = retrieveTree(0)
createPlot(Tree)

我们建造出来的树形图像为:

4、测试和存储决策树

依靠训练数据构造了决策树之后,我们可以将它用于实际数据的分类。在执行数据分类时,需要决策树以及用于构造树的标签向量。然后,程序比较测试数据与决策树上的数值,递归执行该过程直到进入叶子节点;最后将测试数据定义为叶子节点所属的类型。

#分类函数
def classify(inputTree,featLabel,TestVec):firstStr = next(iter(inputTree))secondDict = inputTree[firstStr]featIndex = featLabel.index(firstStr)for key in secondDict.keys():if TestVec[featIndex] == key:if type(secondDict[key]).__name__=='dict':classLabel = classify(secondDict[key],featLabel,TestVec)else :classLabel = secondDict[key]return classLabel

测试代码:

dataSet,labels = createDataSet()#创建数据
T = labels[:] #复制labels
myTree = createTree(dataSet,labels)
ans = classify(myTree,T,[1,0])
print(ans)

输出为:

构造决策树是很耗时的任务,即使处理很小的数据集,如前面的样本数据,也要花费几秒的时间,如果数据集很大,将会耗费很多计算时间。然而用创建好的决策树解决分类问题,则可以很快完成。因此,为了节省计算时间,最好能够在每次执行分类时调用已经构造好的决策树。为了解决这个问题,需要使用Python模块pickle序列化对象。序列化对象可以在磁盘上保存对象,并在需要的时候读取出来。任何对象都可以执行序列化操作,字典对象也不例外。

#决策树的存储
def storeTree(inputTree,filename):import picklefw = open(filename,'wb')pickle.dump(inputTree,fw)fw.close()def grabTree(filename):import picklefr = open(filename, 'rb')return pickle.load(fr)

完整代码:

import numpy as np
from math import log
import operator#创建数据
def createDataSet():dataSet = [[1,1,1],[1,1,1],[1,0,0],[0,1,0],[0,1,0]]#最后一列数据1代表为鱼类,0代表非鱼类labels = ['no surfacing','flippers']return dataSet,labels#计算给定数据的香农熵
def calShannonEnt(dataSet):numEntries = len(dataSet)#返回数据集的行数labelCounts = {}#保存每个标签(Label)出现次数的字典for featVec in dataSet:#对每组特征向量进行统计currentLabel = featVec[-1]if currentLabel not in labelCounts.keys(): #如果标签没有放入统计次数的字典,添加进去labelCounts[currentLabel] = 0labelCounts[currentLabel]+=1shannonEnt = 0.0for key in labelCounts:prob = float(labelCounts[key])/numEntries#选择该标签(Label)的概率shannonEnt = shannonEnt - prob*log(prob,2)#香农熵return shannonEnt#划分数据集
#我们将对每个特征划分数据集的结果计算一次信息熵,然后判断按照那个特征划分数据集是最好的划分方式
def splitDataSet(dataSet,axis,value):retDataSet = []#创建返回的数据集列表for featVec in dataSet:if featVec[axis] ==value:reduceFeatVec = featVec[:axis] #去掉axis特征reduceFeatVec.extend(featVec[axis+1:])#将符合条件的添加到返回的数据集retDataSet.append(reduceFeatVec)return retDataSet#返回划分后的数据集#选择最好的数据集划分方式
def chooseBestFeatureToSplit(dataSet):numFeature = len(dataSet[0])-1#特征数量,-1是因为最后一个是类别baseEntopy = calShannonEnt(dataSet)#计算数据集的香农熵bestInfoGain = 0.0#信息增益bestFeature = -1 #最优特征的索引值for i in range(numFeature):#获取dataSet的第i个所有特征featList = [example[i] for example in dataSet]uniqueVals = set(featList) #创建set集合{},元素不可重复newEntropy = 0.0#计算每种划分方式的信息熵for value in uniqueVals:subDataSet = splitDataSet(dataSet,i,value)#subDataSet划分后的子集prob = len(subDataSet)/float(len(dataSet)) #计算子集的概率newEntropy += prob*calShannonEnt(subDataSet)InfoGain = baseEntopy -newEntropy #信息增益if (bestInfoGain<InfoGain):bestInfoGain = InfoGainbestFeature = ireturn bestFeature#出现次数最多的分类名称
def majorityCnt(classList):classCount = {}for vote in  classList:if vote not in classCount.keys():classCount[vote] = 0classCount[vote]+=1sortedClassCount = sorted(classCount.items(),key = operator.itemgetter(1),reverse = True)return sortedClassCount[0][0]#创建树
def createTree(dataSet,labels):classList = [example[-1] for example in dataSet]if classList.count(classList[0])==len(classList): #如果类别完全相同则停止继续划分return classList[0]if len(dataSet[0])==1:   #遍历完所有特征时返回出现次数最多的类标签return majorityCnt(classList)bestFeat = chooseBestFeatureToSplit(dataSet)   #选择最优特征bestFeatLabel = labels[bestFeat]   #最优特征的标签myTree = {bestFeatLabel:{}}   #根据最优特征的标签生成树del (labels[bestFeat])   #删除已经使用特征标签featValues = [example[bestFeat] for example in dataSet]  #得到训练集中所有最优特征的属性值uniqueVals = set(featValues)     #去掉重复的属性值for valus in uniqueVals:   #遍历特征,创建决策树。subLabels = labels[:]   #复制类标签myTree[bestFeatLabel][valus] = createTree(splitDataSet(dataSet,bestFeat,valus),subLabels)return myTree#分类函数
def classify(inputTree,featLabel,TestVec):firstStr = next(iter(inputTree))secondDict = inputTree[firstStr]featIndex = featLabel.index(firstStr)for key in secondDict.keys():if TestVec[featIndex] == key:if type(secondDict[key]).__name__=='dict':classLabel = classify(secondDict[key],featLabel,TestVec)else :classLabel = secondDict[key]return classLabel#决策树的存储
def storeTree(inputTree,filename):import picklefw = open(filename,'wb')pickle.dump(inputTree,fw)fw.close()def grabTree(filename):import picklefr = open(filename, 'rb')return pickle.load(fr)dataSet,labels = createDataSet()#创建数据
T = labels[:] #复制labels
myTree = createTree(dataSet,labels)
ans = classify(myTree,T,[1,0])
print(ans)
storeTree(myTree,'store.txt')
AnsTree = grabTree('store.txt')

机器学习实战2(决策树篇)相关推荐

  1. 机器学习实战之决策树熵的概述

    机器学习实战之决策树熵的概述 一.决策树简介 二.决策树的一般流程 三.决策树构建的准备工作 1.特征选择 (1)香农熵 (2)编写代码计算经验熵 (3)信息增益 (4)编写代码计算信息增益 2.决策 ...

  2. 机器学习实战——绘制决策树(代码)

    最近在学习Peter Harrington的<机器学习实战>,代码与书中的略有不同,但可以顺利运行. import matplotlib.pyplot as plt# 定义文本框和箭头格式 ...

  3. 机器学习实战之决策树(一)构造决策树

    决策树(一)构造决策树 1.简介 1.1 优缺点 1.2 流程 1.3 决策树的构造 1.4 海洋生物数据 2.信息增益 2.1 几个概念 2.2 计算给定数据集的熵 3 划分数据集 3.1 按照给定 ...

  4. 刻意练习:机器学习实战 -- Task01. 决策树

    背景 这是我们为拥有 Python 基础的同学推出的精进技能的"机器学习实战" 刻意练习活动,这也是我们本学期推出的第三次活动了. 我们准备利用8周时间,夯实机器学习常用算法,完成 ...

  5. 《机器学习实战》—— 决策树

    目录 一.决策树的构造 1. 信息增益 2. 划分数据集 3. 递归构建决策树 二.在 Python 中使用 Matplotlib 注解绘制树形图 1. Matplotlib 2. 构造注解树 三.测 ...

  6. 《机器学习实战》——决策树

    一 决策树 决策树是什么?决策树(decision tree)是一种基本的分类与回归方法.举个通俗易懂的例子,如下图所示的流程图就是一个决策树,长方形代表判断模块(decision block),椭圆 ...

  7. 机器学习实战之决策树

    你是否玩过二十个问题的游戏,游戏的规则很简单:参与游戏的一方在脑海里想某个事物,其他参与者向他提问题,只允许提20个问题,问题的答案也只能用对或错回答.问问题的人通过 推断分解,逐步缩小待猜测事物的范 ...

  8. 《机器学习实战》决策树的应用

    课本中给出的是一个预测隐形眼镜的例子. 数据集样式如下: young    myope    no    reduced    no lenses young    myope    no    no ...

  9. 机器学习实战之决策树(四)示例:预测隐形眼镜类型(含数据集)

    决策树(四)示例:预测隐形眼镜类型 流程 代码 决策树小结 转载请注明作者和出处:https://blog.csdn.net/weixin_45814668 微信公众号:qiongjian0427 知 ...

  10. 机器学习实战(二)决策树DT(Decision Tree、ID3算法)

    目录 0. 前言 1. 信息增益(ID3) 2. 决策树(Decision Tree) 3. 实战案例 3.1. 隐形眼镜案例 3.2. 存储决策树 3.3. 决策树画图表示 学习完机器学习实战的决策 ...

最新文章

  1. 民族、学历学位、所学专业、、专业技术职务 对应表
  2. 基于Manim针对FT教学过程的一种可行性设计
  3. SQL进阶随笔--case用法(一)
  4. http GET 和 POST 请求的优缺点和误区 --前端优化
  5. dubbo指定服务提供者ip_使用指定IP调用Dubbo服务
  6. SpringCloud Eureka自我保护机制介绍及配置
  7. facebook 开源_Facebook开源主管开放
  8. 【译】5 个你需要知道的 JavaScript 小技巧
  9. Mac使用Docker搭建python测试执行环境
  10. 计算机应用与基础app,手机APP支持下《计算机应用基础》课程探究性学习活动设计与实验研究...
  11. R语言--Cox模型校准曲线原理(一)数据来源
  12. VirtualBox如何添加ISO文件
  13. 企查查的批量公司查找
  14. FPGA学习:Verilog基本语法
  15. 圈内著名ts_央视为电竞发声:AG和estar当选著名战队,梦泪,猫神被官方肯定
  16. RCNN到faster RCNN 简介
  17. DICOM协议学习笔记(二)
  18. 建筑八大员培训湖北劳务员培训建筑劳务人员实名制管理的问题
  19. 将小写金额转换成中文大写
  20. 计算机网络各层设备及功能讲解大汇总~

热门文章

  1. python 路由_静态路由配置
  2. 关于“前台根据后台值,操作字段、显示或select选中状态”的几种做法
  3. 什么是H3C的BFD MAD
  4. win7防火墙怎么关_电脑防火墙怎么关?这两招你得会
  5. duplicate symbol _OBJC_CLASS 错误处理方法
  6. 计算机科学与生命科学的关系,计算机科学与生命科学论文
  7. ipad使用的PDF书籍没有目录怎么办?
  8. SQL Server ansi_null_default | ansi_null_dflt_on
  9. 2021巢湖第一中学高考成绩查询,2021年巢湖高中学校排名及录取分数线排名
  10. 「macOS无法验证此APP不包含恶意软件」的处理方式