目录
逻辑回归
算法原理
决策树
决策树算法概述
树的组成
决策树的训练与测试
切分特征
衡量标准--熵
信息增益
决策树构造实例
连续值问题解决
预剪枝方法
分类与回归问题解决
决策树解决分类问题步骤
决策树解决回归问题步骤
决策树代码实例
集成算法
Bagging模型
使用Bagging模型的示例代码
Boosting模型
AdaBoost
Stacking模型
支持向量机
决策边界
距离的计算
数据标签定义
优化的目标
目标函数
拉格朗日乘子法
SVM求解
SVM求解实例
soft-margin
低维不可分问题
逻辑回归是一种用于解决二分类问题的机器学习分类算法。它通过将输入特征与权重相乘,并加上偏置项,然后将结果通过一个称为“sigmoid函数”的激活函数进行转换,得到一个介于0和1之间的概率值。这个概率值表示样本属于正类的概率。
决策树算法是一种有监督学习算法,它通过构建树形结构的模型来进行决策。决策树的原理是基于特征选择和节点划分的思想。
特征选择是指从所有特征中选择一个最优的特征作为当前节点的划分标准。常用的特征选择方法有信息增益、信息增益比、基尼指数等。这些方法都是通过计算特征对于分类结果的重要性来选择最优特征。
节点划分是指根据选定的特征将数据集划分为不同的子集。每个子集对应一个分支,分支上的样本具有相同的特征值。节点划分的目标是使得每个子集中的样本尽可能属于同一类别,即增加纯度。
决策树的构建过程是递归的,从根节点开始,根据特征选择和节点划分的原则,逐步构建子树,直到满足终止条件。终止条件可以是达到预定的树深度、节点中的样本数小于某个阈值或者节点中的样本属于同一类别。
决策树算法是一种基于树形结构的分类学习方法。它通过对数据集进行递归地划分,构建一颗由多个判断节点组成的树。每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果。
决策树算法的概述如下:
1. 选择最佳划分属性:根据某个评价指标(如信息增益、基尼指数等),选择最佳的属性作为当前节点的划分属性。
2. 划分数据集:根据划分属性的取值,将数据集划分为多个子集,每个子集对应一个分支。
3. 递归构建子树:对每个子集,重复步骤1和步骤2,递归地构建子树,直到满足终止条件(如节点中的样本属于同一类别,或者没有更多属性可供划分)。
4. 剪枝处理:为了避免过拟合,可以对构建好的决策树进行剪枝处理,即去掉一些不必要的节点和分支。
5. 预测分类结果:根据构建好的决策树,对新样本进行分类预测。
决策树算法的优点包括易于理解和解释、能够处理离散型和连续型属性、能够处理多分类问题等。然而,决策树算法也存在一些缺点,如容易过拟合、对噪声敏感等。
熵是衡量信息或数据的不确定性和随机性的量化指标。熵的大小与不确定性成正比,即越大的熵表示数据越随机、越不确定。而越小的熵则表示数据越有序、越确定。可以将熵看作数据中所包含的信息量,当熵最大时,数据中的每个元素都是等概率出现的,难以从中获得有用的信息;而当熵最小时,数据中的每个元素都具有确定性,从中获得的信息量很小。
在机器学习中,熵经常用于衡量分类问题中的不确定性。在决策树算法中,通过计算每个特征的熵来选择分裂节点,以达到最佳的分类效果。熵可以帮助我们理解数据的分布情况和模型的性能,同时也可以作为评估模型预测结果质量的指标之一。
信息增益是一种用于决策树算法中的指标,用于衡量特征对于分类任务的重要性。它衡量了在划分数据集之前和之后,分类的不确定性减少的程度。信息增益越大,表示使用该特征进行划分能够获得更多的信息,从而更好地分类数据。
计算信息增益的步骤如下:
1. 计算划分前的数据集的信息熵(Entropy)作为基准。
2. 对于每个特征,计算该特征划分后的加权平均信息熵。
3. 计算每个特征的信息增益,即划分前的信息熵减去划分后的加权平均信息熵。
数据:14天打球情况
特征:4种环境变化——outlook、temperature、humidity、windy;标签为 play
目标:构造决策树
划分方式:4种
贪婪算法是一种基于贪婪策略的算法,它在每一步选择中都采取当前状态下最优的选择,而不考虑全局最优解。贪婪算法通常适用于求解最优化问题,其中问题的解可以通过一系列局部最优选择来构建。
贪婪算法的概述如下:
1. 初始化:选择一个初始解作为当前解。
2. 选择:从可行解集合中选择一个局部最优解作为当前解的下一步。
3. 更新:更新当前解为新的局部最优解。
4. 终止条件:重复步骤2和步骤3,直到满足终止条件。
贪婪算法的特点是简单、高效,并且通常能够在较短的时间内找到一个近似最优解。然而,由于贪婪算法只考虑局部最优解,而不考虑全局最优解,因此不能保证一定能够找到全局最优解。
贪婪算法在许多问题中都有应用,例如最短路径问题、背包问题、赫夫曼编码等。它可以通过选择当前状态下的最优解来解决这些问题,从而得到一个近似最优解。
例如,以下体重哪些属于适合打篮球那些不适合打篮球。
首先将数据进行从小到大排序:60 70 75 85 90 95 100 120 125 220,若进行“二分”则可能有9个分界点,分别计算分割后的增益找到最优解。实际上就是“离散化”过程。
预剪枝:边建立决策树边进行剪枝的操作(更实用)限制深度,叶子节点个数,叶子节点样本数,设置信息增益量将不达标的减去等
预剪枝(pre-pruning)是在决策树构建过程中,在每个节点上进行判断,如果当前节点的划分不能带来决策树泛化性能的提升,就停止划分并将当前节点标记为叶子节点。预剪枝的优点是构建速度快,但可能会导致欠拟合,即决策树无法充分利用训练数据的特征。
决策树是一种常用的解决分类问题的算法。它通过构建一棵树来对数据进行分类。决策树的构建过程是基于特征的划分,每个内部节点代表一个特征,每个叶节点代表一个类别。
决策树的构建过程如下:
1. 选择一个特征作为根节点,将数据集按照该特征的取值进行划分。
2. 对每个子数据集,重复步骤1,选择一个最佳的特征作为子节点,并继续划分数据集。
3. 重复步骤2,直到满足终止条件,例如所有数据属于同一类别或者数据集为空。
决策树的分类过程如下:
1. 对于一个新的样本,从根节点开始,根据样本的特征值选择相应的子节点。
2. 继续在子节点中进行选择,直到到达叶节点。
3. 将叶节点所代表的类别作为预测结果。
决策树的优点是易于理解和解释,可以处理离散和连续特征,对缺失值也有一定的容忍度。然而,决策树容易过拟合,特别是当树的深度较大时。为了避免过拟合,可以使用剪枝技术,如预剪枝和后剪枝。
决策树可以通过构建回归树来解决回归问题。回归树是将数据空间划分为多个子空间,并为每个子空间分配一个预测值。下面是决策树解决回归问题的步骤:
1. 选择一个特征和一个切分点,将数据集划分为两个子集。
2. 对于每个子集,计算目标变量的平均值作为预测值。
3. 计算划分后的子集的均方误差(MSE)。
4. 选择最佳的特征和切分点,使得划分后的子集的均方误差最小化。
5. 重复步骤1-4,直到满足停止条件(例如达到最大深度或子集中的样本数量小于阈值)。
6. 最终得到一个回归树,可以用于预测新的数据样本。
通过构建回归树,决策树可以根据输入特征预测连续型目标变量的值。回归树的构建方法与分类树类似,但是在每个节点上使用的划分准则不同。回归树使用均方误差(MSE)作为划分准则,以最小化预测值与真实值之间的差异。
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
from math import log
import operator
def createDataSet():
# 四组特征,一个标签
dataSet = [[0, 0, 0, 0, 'no'],
[0, 0, 0, 1, 'no'],
[0, 1, 0, 1, 'yes'],
[0, 1, 1, 0, 'yes'],
[0, 0, 0, 0, 'no'],
[1, 0, 0, 0, 'no'],
[1, 0, 0, 1, 'no'],
[1, 1, 1, 1, 'yes'],
[1, 0, 1, 2, 'yes'],
[1, 0, 1, 2, 'yes'],
[2, 0, 1, 2, 'yes'],
[2, 0, 1, 1, 'yes'],
[2, 1, 0, 1, 'yes'],
[2, 1, 0, 2, 'yes'],
[2, 0, 0, 0, 'no']]
# 第一列年龄、第二列工作等级、第三列买没买房、第四列贷款记录、第五列会不会带给用户
labels = ['F1-AGE', 'F2-WORK', 'F3-HOME', 'F4-LOAN']
return dataSet, labels
# 创建树模型
# 参数:数据集、标签(列名)、根节点排列
def createTree(dataset,labels,featLabels):
# 1.判断节点标签是否一致(停止条件)
# 将dataset中的数据按行依次放入example中,
# 然后取得example中的最后一列元素,将这些元素放入列表classList中。
classList = [example[-1] for example in dataset]
# 2.计算列表中元素是否完全相同,即是否全为yes或者全为no(停止条件)
if classList.count(classList[0]) == len(classList):
# 返回第一个元素值即相同类别值
return classList[0]
# 3.当dataSet数据集中的值只剩下一列标签时,说明数据集已遍历完成,返回最多的类别
if len(dataset[0]) == 1:
# majorityCnt()函数计算每列中最多的类别
return majorityCnt(classList)
# chooseBestFeatureToSplit()函数选择最好的特征进行分割
# 4.遍历整个数据集选择最优的特征,结果返回一个索引值
bastFeat = chooseBestFeatureToSplit(dataset)
# 5.获取索引值实际对应的名称
bastFeatLabel = labels[bastFeat]
# 6.得到树模型的根节点
featLabels.append(bastFeatLabel)
# 7.构建树模型整体结构,第一次得到根节点随后依次嵌套
myTree = {bastFeatLabel:{}}
# 8.每完成一次删除当前索引
del labels[bastFeat]
# 统计当前列中有多少不一样的值,例如只有0和1则树模型分为两个分支若含有多个则分为多个分支
# 获取当前列的所有特征
featValue = [example[bastFeat] for example in dataset]
# 去除重复值,得到具体的分支个数
uniqueVals = set(featValue)
# 对于每个分支再进行分支
for value in uniqueVals:
# 切分完之后的labels
sublabels = labels[:]
# 在当前最好的节点下继续构建分支
# splitDataSet()函数切分当前的数据集
# featLabels控制树模型的特征先用哪个后用哪个
myTree[bastFeatLabel][value] = createTree(splitDataSet(dataset, bastFeat, value), sublabels, featLabels)
return myTree
# 计算每列中最多的类别
def majorityCnt(classList):
classCount = {}
# 遍历classList中的每个元素vote。
# 如果vote不在classCount的键中,就将vote作为键添加到classCount中,
# 并将对应的值设为1。如果vote已经在classCount的键中,就将对应的值加1
for vote in classList:
if vote not in classCount.keys(): classCount[vote] = 0
classCount[vote] += 1
# 函数使用sorted函数对classCount进行排序,按照值的大小进行降序排序,并返回排序后的结果中的第一个元素的第一个值
sortedclassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
# 返回出现最多的
return sortedclassCount[0][0]
# 选择最好的特征进行分割
"""
1.首先,获取数据集中特征的数量,即numFeatures = len(dataset) - 1。
2.然后,计算整个数据集的熵,即baseEntropy = calcShannonEnt(dataset)。熵是衡量数据集的无序程度的指标。
3.接下来,初始化最佳信息增益为0,最佳特征索引为-1。
4.使用一个循环遍历每个特征:
4-1.获取当前特征的所有取值,即featList = [example[i] for example in dataset]。
4-2将特征的取值转化为集合,即uniqueVals = set(featList)。
4-3初始化新的熵为0。
4-4对于每个特征取值,将数据集按照当前特征的取值进行划分,得到子数据集subDataSet。
4-5计算子数据集的概率,即prob = len(subDataSet)/float(len(dataset))。
4-6计算子数据集的熵,即newEntropy += prob * calcShannonEnt(subDataSet)。
4-7计算信息增益,即infoGain = baseEntropy - newEntropy。
4-8如果当前信息增益大于最佳信息增益,则更新最佳信息增益和最佳特征索引。
5.返回最佳特征索引bestFeature。
"""
# 函数的输入参数是一个数据集dataset,函数的返回值是一个整数,表示最佳特征的索引
def chooseBestFeatureToSplit(dataset):
# 获取数据集中特征的数量
numFeatures = len(dataset[0]) - 1
"""计算熵值,利用信息增益找到最优特征"""
# 原始熵值
# calcShannonEnt()计算熵值函数
baseEntropy = calcShannonEnt(dataset)
# 设置信息增益值
bestInfoGain = 0
# 设置最好特征
bestFeature = -1
# 遍历每个特征
for i in range(numFeatures):
# 获取当前列特征
featList = [example[i] for example in dataset]
# 获取唯一个数
uniqueVals = set(featList)
newEntropy = 0
# 遍历特征中的每个值
for val in uniqueVals:
# 得到划分好的数据
subDataSet = splitDataSet(dataset, i, val)
# 计算实际熵值
prob = len(subDataSet) / float(len(dataset))
# 更新熵值
newEntropy += prob * calcShannonEnt(subDataSet)
# 定义新的信息增益值
infoGain = baseEntropy - newEntropy
if (infoGain > bestInfoGain):
bestInfoGain = infoGain
bestFeature = i
return bestFeature
# 切分数据集
def splitDataSet(dataset, axis, val):
# 创建一个空列表,用于存储划分后的子集
retDataSet = []
# 遍历数据集中的每个样本
for featVec in dataset:
# 如果样本的第axis个特征值等于给定的特征值val
if featVec[axis] == val:
# 将样本中除了第axis个特征之外的特征值存储到reducedFeatVec中
reducedFeatVec = featVec[:axis]
# 将样本中第axis个特征之后的特征值添加到reducedFeatVec中
reducedFeatVec.extend(featVec[axis + 1:])
# 将划分后的样本添加到retDataSet中
retDataSet.append(reducedFeatVec)
# 返回划分后的子集
return retDataSet
# 计算熵值
def calcShannonEnt(dataset):
# 所有数量
numexamples = len(dataset)
# 每个标签出现的次数,即yes出现多少个,no出现多少个
labelCounts = {}
# 对于每个样本进行遍历查看为yes还是no
for featVec in dataset:
# 查看当前样本的标签值
currentlabel = featVec[-1]
# 当前样本不在字典中
if currentlabel not in labelCounts.keys():
labelCounts[currentlabel] = 0
labelCounts[currentlabel] += 1
# 设置原始熵值为0,通过具体计算改变熵值
shannonEnt = 0
# 有多少类别就遍历多少次
for key in labelCounts:
# 概率值 = 个数/总数
prop = float(labelCounts[key]) / numexamples
# shannonEnt += -prop * log(prop, 2)
shannonEnt -= prop * log(prop, 2)
return shannonEnt
# 决策树绘制
def getNumLeafs(myTree):
numLeafs = 0
firstStr = next(iter(myTree))
secondDict = myTree[firstStr]
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':
numLeafs += getNumLeafs(secondDict[key])
else: numLeafs +=1
return numLeafs
def getTreeDepth(myTree):
maxDepth = 0
firstStr = next(iter(myTree))
secondDict = myTree[firstStr]
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':
thisDepth = 1 + getTreeDepth(secondDict[key])
else: thisDepth = 1
if thisDepth > maxDepth: maxDepth = thisDepth
return maxDepth
def plotNode(nodeTxt, centerPt, parentPt, nodeType):
arrow_args = dict(arrowstyle="<-")
font = FontProperties(fname=r"c:\windows\fonts\simsunb.ttf", size=14)
createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction',
xytext=centerPt, textcoords='axes fraction',
va="center", ha="center", bbox=nodeType, arrowprops=arrow_args, FontProperties=font)
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, va="center", ha="center", rotation=30)
def plotTree(myTree, parentPt, nodeTxt):
decisionNode = dict(boxstyle="sawtooth", fc="0.8")
leafNode = dict(boxstyle="round4", fc="0.8")
numLeafs = getNumLeafs(myTree)
depth = getTreeDepth(myTree)
firstStr = next(iter(myTree))
cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW, plotTree.yOff)
plotMidText(cntrPt, parentPt, nodeTxt)
plotNode(firstStr, cntrPt, parentPt, decisionNode)
secondDict = myTree[firstStr]
plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':
plotTree(secondDict[key],cntrPt,str(key))
else:
plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalW
plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)
plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))
plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD
def createPlot(inTree):
fig = plt.figure(1, facecolor='white') #创建fig
fig.clf() #清空fig
axprops = dict(xticks=[], yticks=[])
createPlot.ax1 = plt.subplot(111, frameon=False, **axprops) #去掉x、y轴
plotTree.totalW = float(getNumLeafs(inTree)) #获取决策树叶结点数目
plotTree.totalD = float(getTreeDepth(inTree)) #获取决策树层数
plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0; #x偏移
plotTree(inTree, (0.5,1.0), '') #绘制决策树
plt.show()
if __name__ == '__main__':
dataset, labels = createDataSet()
featLabels = []
myTree = createTree(dataset,labels,featLabels)
createPlot(myTree)
集成学习(Ensemble learning)是一种通过组合多个弱分类器来构建一个强分类器的机器学习算法。它通过在数据上构建多个模型,并将所有模型的建模结果集成起来,以获得更好的回归或分类表现。集成学习在各个机器学习领域都有广泛的应用,例如市场营销模拟、客户统计、疾病风险预测等。
集成学习可以分为三类算法:装袋法(Bagging)、提升法(Boosting)和堆叠法(Stacking)。
装袋法的核心思想是构建多个相互独立的评估器,然后对它们的预测结果进行平均或多数表决来决定集成评估器的结果。常见的装袋法算法有随机森林(Random Forest)。
提升法中,基评估器是相关的,是按顺序一一构建的。它的核心思想是通过多次迭代,结合弱评估器的力量对难以评估的样本进行预测,从而构建一个强评估器。常见的提升法算法有梯度提升树(Gradient Boosting Tree)和XGBoost。
堆叠法的特点是使用第一阶段的预测结果作为下一阶段的特征,以提高模型的非线性表达能力和降低泛化误差。堆叠法的目标是同时降低模型的偏差和方差。
总结起来,集成学习通过组合多个模型的建模结果,以获得更好的回归或分类表现。装袋法通过构建多个相互独立的评估器来决定集成评估器的结果,提升法通过迭代构建强评估器,堆叠法通过使用预测结果作为特征来提高模型的表达能力。
Bagging模型是一种集成学习方法,它通过对训练集进行有放回的随机抽样,构建多个基学习器并通过对基学习器的预测结果进行投票或平均来得到最终的预测结果。Bagging模型的主要步骤如下:
随机抽样:从训练集中有放回地随机抽取一定数量的样本,构成新的训练集。
基学习器训练:使用新的训练集训练多个基学习器。每个基学习器可以使用不同的算法或参数设置。
预测结果集成:对于分类问题,可以通过投票的方式来集成基学习器的预测结果;对于回归问题,可以通过平均的方式来集成基学习器的预测结果。
Bagging模型的优点包括:
Bagging模型的缺点包括:
说白了就是并行训练一堆分类器,最典型的代表就是随机森林。随机:数据采样随机,特征选择随机;森林:很多个决策树并行放在一起。之所以要进行随机,是要保证泛化能力,如果树都一样,那就没意义了。
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
# 创建基学习器
base_estimator = DecisionTreeClassifier()
# 创建Bagging模型
bagging_model = BaggingClassifier(base_estimator=base_estimator, n_estimators=10)
# 训练模型
bagging_model.fit(X_train, y_train)
# 预测结果
y_pred = bagging_model.predict(X_test)
Boosting模型是一种集成学习方法,它通过串行训练多个弱学习器来构建一个强学习器。Boosting模型的主要思想是通过迭代的方式,每一轮迭代都根据前一轮的结果来调整样本的权重,使得前一轮分类错误的样本在下一轮中得到更多的关注。最终,将所有弱学习器的预测结果进行加权组合,得到最终的预测结果。
在Boosting模型中,有几个经典的算法被广泛应用,包括AdaBoost、GBDT和XGBoost。
1. AdaBoost(Adaptive Boosting)是一种最早提出的Boosting算法。它通过迭代训练多个弱分类器,每一轮迭代都根据前一轮的分类结果来调整样本的权重,使得前一轮分类错误的样本在下一轮中得到更多的关注。最终,将所有弱分类器的预测结果进行加权组合,到最终的预测结果。
2. GBDT(Gradient Boosting Decision Tree)是一种基于决策树的Boosting算法。它通过迭代训练多个决策树模型,每一轮迭代都根据前一轮的残差来训练下一棵决策树。最终,将所有决策树的预测结果进行加权组合,得到最终的预测结果。
3. XGBoost(eXtreme Gradient Boosting)是一种基于GBDT的Boosting算法的优化版本。它在GBDT的基础上引入了正则化项和二阶导数信息,进一步提高了模型的性能和泛化能力。
这些Boosting模型在机器学习和数据挖掘领域都有广泛的应用,可以用于分类问题和回归问题。
AdaBoost(Adaptive Boosting)是一种集成学习方法,它通过组合多个弱学习器来构建一个强学习器。它的核心思想是通过迭代训练一系列弱分类器,并根据每个弱分类器的表现来调整样本的权重,使得在下一轮训练中更加关注被前一轮分类错误的样本。最终,将这些弱分类器的结果进行加权组合,得到一个更准确的分类结果。
AdaBoost的训练过程如下:
1. 初始化样本权重,使得每个样本的权重相等。
2. 迭代训练弱分类器。在每一轮迭代中,根据当前样本权重训练一个弱分类器,并计算分类错误率。
3. 根据分类错误率计算弱分类器的权重,错误率越低的弱分类器权重越高。
4. 更新样本权重,增加被错误分类的样本的权重,减少被正确分类的样本的权重。
5. 重复步骤2-4,直到达到预定的迭代次数或分类错误率达到要求。
6. 将所有弱分类器的结果进行加权组合,得到最终的分类结果。
AdaBoost的优点是能够提高分类的准确性,并且对于弱分类器的选择没有太多限制。然而,它也有一些缺点,比如对噪声敏感,容易过拟合,以及对弱分类器的训练时间较长。
Stacking模型是一种集成学习方法,它将多个单一模型以一定的方式组合起来,以获得更好的预测性能。Stacking模型的基本思想是将多个不同的基础模型进行堆叠,其中一个模型作为最终的预测模型,而其他模型则作为该模型的输入。
Stacking模型的训练过程分为两个阶段。首先,使用训练数据对每个基础模型进行训练。然后,使用这些基础模型的预测结果作为输入,再训练一个元模型(也称为组合模型或次级模型)。元模型使用基础模型的预测结果作为特征,以生成最终的预测结果。
Stacking模型的优点在于它可以结合各个单项预测模型的优点,从而提高整体的预测性能。通过使用不同类型的基础模型,Stacking模型可以捕捉到不同模型的优势,并在预测中进行综合利用。
范例: 假设我们有三个基础模型:模型A、模型B和模型C。我们使用训练数据对这三个模型进行训练,并得到它们的预测结果。然后,我们将这些预测结果作为特征,再训练一个元模型D。最终,我们可以使用元模型D来进行预测。
# 训练基础模型
model_A.fit(X_train, y_train)
model_B.fit(X_train, y_train)
model_C.fit(X_train, y_train)
# 得到基础模型的预测结果
pred_A = model_A.predict(X_test)
pred_B = model_B.predict(X_test)
pred_C = model_C.predict(X_test)
# 将基础模型的预测结果作为特征,训练元模型
X_meta = np.column_stack((pred_A, pred_B, pred_C))
model_D.fit(X_meta, y_train)
# 使用元模型进行预测
pred_final = model_D.predict(X_meta_test)
支持向量机(Support Vector Machine,SVM)是一种常用的监督学习算法,主要用于分类和回归问题。其原理基于统计学习理论中的结构风险最小化原则。
SVM的目标是找到一个最优的超平面,能够将不同类别的样本点在特征空间中划分开来,并且使得两侧距离最近的样本点到超平面的距离最大化。这些距离最近的样本点被称为支持向量。
具体来说,SVM的原理可以概括为以下几个步骤:
SVM具有以下特点和优势:
需要注意的是,SVM的训练过程涉及到优化问题的求解,通常采用凸优化算法进行求解,例如序列最小优化(SMO)算法。
在支持向量机(SVM)中,决策边界是通过找到能够将不同类别样本分开的最优超平面来实现的。这个最优超平面被选为距离两个不同类别的样本最远的点的平均位置。这些最远的点被称为支持向量,它们决定了决策边界的位置。
决策边界的形状可以是线性的,也可以是非线性的。在线性可分的情况下,决策边界是一个直线或超平面。在非线性可分的情况下,可以使用核函数将数据映射到高维空间中,从而使其在高维空间中线性可分。决策边界的选择对分类器的性能和泛化能力有很大影响。一个合理的决策边界可以更好地区分不同类别的样本,并对新样本进行准确分类。