机器学习小知识--面试得一塌糊涂

  • 机器学习中需要归一化的算法有SVM, 逻辑回归,神经网络,KNN, 线性回归,而树形结构的不需要归一化,因为它们不关心变量的值,而是关心变量分布和变量之间的条件概率,如决策树,随机森林,对于树形结构。树模型的构造是通过寻找最优分裂点构成的,样本点的数值缩放不影响分裂点的位置,对树模型的结构不造成影响,而且树模型不能进行梯度下降,因为树模型是阶跃的,阶跃是不可导的,并且求导没意义,也不需要归一化

  • 对于那些需要归一化的模型,主要是因为特征值相差很大时,运用梯度下降,损失等高线是椭圆形,需要进行多次迭代才能达到最优点,如果进行归一化了,那么等高线就是圆形的,促使SGD往原点迭代,从而导致需要迭代次数较少。

  • 归一化:把每个特征向量(特别是奇异样本数据)的值都缩放到相同数值范围。如[0,1]或[-1,1]。

  • 常见机器学习算法的优缺点_为什么adaboost不适合使用高维稀疏特征?-CSDN博客

处理类别型特征
  • 在机器学习中,大多数算法,譬如逻辑回归,支持向量机SVM,k近邻算法等都只能够处理数值型数据,不能处理文字,在sklearn当中,除了专用来处理文字的算法,其他算法在fit的时候全部要求输入数组或矩阵,也不能够导入文字型数据(其实手写决策树和朴素贝叶斯可以处理文字,但是sklearn中规定必须导入数值型)。

  • 并不是所有的类别型特征都能统一的转换为数值型,在转换之前要先对类别进行一个分析,总体来说,类别型特征可以分为定类变量、定序变量、定距变量和定比变量

    • 定类变量:如性别(男、女、其他),三种取值之间是相互独立的,彼此之间完全没有关系,这种变量称之为名义变量。

    • 定序变量:如学历(小学、初中、高中),三种取值不是完全独立的,我们可以明显看出,在性质上可以有高中>初中>小学这样的联系,学历有高低,但是学历的取值之间却不是可以计算的,我们不能说小学 + 某个取值 = 初中。这是有序变量。

    • 定距变量:如温度(>25摄氏度、>30摄氏度 、>35摄氏度),各个取值之间有联系,且是可以互相计算的,而且两者的差值有意义。比如35摄氏度 - 25摄氏度 = 10摄氏度,分类之间可以通过数学计算互相转换。这是有距变量。

    • 定比变量:如质量(>10kg、>50kg、>100kg),各个取值之间有联系,不仅可以计算差值,还可以计算其商值。

  • 然而在对特征进行编码的时候,这四种分类数据都会被我们转换为[0,1,2],这三个数字在算法看来,是连续且可以计算的,这三个数字相互不等,有大小,并且有着可以相加相乘的联系。所以算法会把性别、血型这样的分类特征都误会成是质量这样的分类特征。这是说,我们把分类转换成数字的时候,忽略了数字中自带的数学性质,所 以给算法传达了一些不准确的信息,而这会影响我们的建模。这里主要三种方法,分别是序号编码、独热编码二进制编码

    • 可以通过导入sklearn.preprocessing中的OrdinalEncoder进行处理。

    • 可以通过导入sklearn.preprocessing中的OneHotEncoder,创建哑变量进行处理。

特征组合
  • 组合特征也叫特征交叉(Feature Crosses),即不同类型或者不同维度特征之间的交叉组合,其主要目的是为了弥补CTR场景中早期的模型无法有效的进行特征组合而产生的想法和实践,随着算法模型的进步,虽然一些机器学习排序模型(GBDT+LR、FM等)和深度学习排序模型能够捕获特征之间的联系,但是前期仍然会生成一些组合特征,比如用户在某些类别下的行为统计,性别下的数据统计等。

  • 在实际的场景中,往往会结合数据分析去挖掘潜在的价值特征组合。这时候便会借助数据分析、数据挖掘、分析者的敏感直觉和对业务的深入理解去进行挖掘。

  • 为了提高复杂关系的拟合能力,在特征工程中经常会把一阶离散特征两两组合,构成高阶组合特征。可以采取降维,矩阵分解或者特征筛选的方法得到具备绝大部分信息的几个特征进行训练

  • 组合特征是指多个特征组合起来,作为新的特征,组合的方法有:基本运算、聚合、聚合后进行基本运算等。组合高阶特征可以对类别特征进行embedding、然后对特征实施FM特征组合。

QQ图
  • 统计学里Q-Q图(Q代表分位数)是一个概率图,用图形的方式比较两个概率分布,把他们的两个分位数放在一起比较。首先选好分位数间隔。图上的点(x,y)反映出其中一个第二个分布(y坐标)的分位数和与之对应的第一分布(x坐标)的相同分位数。因此,这条线是一条以分位数间隔为参数的曲线。

  • 如果两个分布相似,则该Q-Q图趋近于落在y=x线上。如果两分布线性相关,则点在Q-Q图上趋近于落在一条直线上,但不一定在y=x线上。Q-Q图可以用来可在分布的位置-尺度范畴上可视化的评估参数。

为什么要对特征做归一化处理
  • Feature scaling,常见的提法有“特征归一化”、“标准化”,是数据预处理中的重要技术。特征间的单位(尺度)可能不同,比如身高和体重,比如摄氏度和华氏度,比如房屋面积和房间数,一个特征的变化范围可能是[ 1000 , 10000 ] [1000, 10000][1000,10000],另一个特征的变化范围可能是[ − 0.1 , 0.2 ] [-0.1, 0.2][−0.1,0.2],在进行距离有关的计算时,单位的不同会导致计算结果的不同,尺度大的特征会起决定性作用,而尺度小的特征其作用可能会被忽略,为了消除特征间单位和尺度差异的影响,以对每维特征同等看待,需要对特征进行归一化
欧氏距离和曼哈顿距离
  • 欧氏距离:欧几里得距离,就是平方和开根号。我们最常用的。欧氏距离越小,两个向量的相似度越大;欧氏距离越大,两个向量的相似度越小。

  • 曼哈顿距离:|x1 - x2| + |y1 - y2|, 曼哈顿距离也称为城市街区距离。可以看出在曼哈顿距离中,考虑了更多的实际 因素。总之,在曼哈顿距离的世界中,规则是我们只能沿着线画出的格子行进。

  • 切比雪夫距离:max(|x1 - x2|,|y1 - y2|)

余弦相似度
  • 对于两个向量A和B,其余弦相似度定义为cos(A,B)= A*B / |A|*|B| 即两个向量夹角的余弦,关注的是向量之间的角度关系,并不关心它们的绝对大小,余弦相似度依然符合“相同为1,正交为0,相反为-1”的性质,其取值范围是[-1,1]。欧式距离衡量空间点的直线距离,余弦距离衡量点在空间的方向差异。欧式距离体现的数值上的绝对差异,而余弦距离体现方向上的相对差异。
one-hot的作用
  • One-Hot编码是分类变量作为二进制向量的表示。这首先要求将分类值映射到整数值。然后,每个整数值被表示为二进制向量,除了整数的索引之外,它都是零值,它被标记为1。直接使用数字会给将人工误差而导致的假设引入到类别特征中,比如类别之间的大小关系,以及差异关系等等
过拟合和欠拟合
  • 过拟合:训练集上表现很好,测试集上表现很差。欠拟合:训练集和测试集都上表现很差。欠拟合会导致高 Bias ,过拟合会导致高 Variance ,所以模型需要在 Bias 与 Variance 之间做出一个权衡。
降低欠拟合的方法
  • 增加新特征,可以考虑加入进特征组合、高次特征,来增大假设空间;

  • 尝试非线性模型,比如核SVM 、决策树、DNN等模型;

  • 如果有正则项可以较小正则项参数 λ \lambda λ;

  • Boosting ,Boosting 往往会有较小的 Bias,比如 Gradient Boosting 等.

解决过拟合的方法
  • 增加数据量,数据增强(data augmentation):通过一定规则来扩充数据,比如旋转,平移,亮度,切割等手段一张图片得到多张。

  • 运用正则化技术,限制模型的复杂度,dropout

  • 贝叶斯方法: 假如样本是从上帝才知道的某个分布中抽样而来,那么data augmentation 就是希望样本集分布能接近先验。假如有上帝才知道的某个完美模型作为先验,那么我们对模型的修剪自己ensemble ,那就是让修剪后的假设空间和融合后的假设空间更加接近先验。从参数的角度来说,这是直接的贝叶斯了,L2认为参数符合高斯先验,L1符合拉普拉斯先验。

  • 多种模型组合:训练多个模型,以每个模型的平均输出作为结果。

    • Bagging:简单理解,就是分段函数的概念:用不同的模型拟合不同部分的训练集。以随机森林(Rand Forests)为例,就是训练了一堆互不关联的决策树。但由于训练神经网络本身就需要耗费较多自由,所以一般不单独使用神经网络做Bagging。可并行的集成方法。每个基模型可以分别、独立、互不影响地生成。主要降低 Variance,对 Bias 无明显作用。因此,适用于 High Variance & Low Bias 的模型。

    • Boosting:Boosting的核心思想是将多个弱分类器组装成一个强分类器 。通过提高那些在前一轮被弱分类器分错样例的权值,减小前一轮分对样例的权值,来使得分类器对误分的数据有较好的效果。通过加法模型将弱分类器进行线性组合,比如AdaBoost通过加权多数表决的方式,即增大错误率小的分类器的权值,同时减小错误率较大的分类器的权值。而提升树通过拟合残差的方式逐步减小残差,将每一步生成的模型叠加得到最终模型。序贯式集成方法(Sequential Ensemble)。每轮迭代生成的基模型,主要提升前一代基模型表现不好的地方。不断迭代弱分类器,从而降低 Bias。因此,适用于 Low Variance & High Bias 的模型

时序预测任务
  • 单指标时序预测任务:给定某一个指标的历史变化情况,预测其在未来一段时间内的变化。

  • 多指标时序预测任务:给定某几个指标的历史变化情况,预测其在未来一段时间内的变化。该任务与单指标时序预测任务的区别在于,几个指标之间不一定相互独立,而是存在某种影响。

  • 时序异常检测任务:从正常的时间序列中识别不正常的事件或行为的过程。可以从历史数据中检测,也可以基于时序预测对尚未发生的异常做出预警。

  • 时序指标聚类:将变化趋势类似的时序指标归至同一类别。在实际运维工作中,面对的指标可能成百上千,分别对其进行分析,工作量太大,可以在聚类的基础上再做建模分析。

  • 指标关联分析:即分析指标A是否会对指标B有影响,以及有什么样的影响(正向/负向、先后关系、多少时间步后造成影响等等)。

线性回归
  • 线性回归是一种线性模型,它对异常值非常敏感。它假设输入变量 (X) 和单个输出变量 (y) 之间存在线性关系。 一般来说,有两种情况:

    • 单变量线性回归:它对单个输入变量(单个特征变量)和单个输出变量之间的关系进行建模。

    • 多变量线性回归(也称为多元线性回归):它对多个输入变量(多个特征变量)和单个输出变量之间的关系进行建模。Scikit-learn 的 PolynomialFeatures 内置了这种方法。 首先,我们需要生成一个由所有具有指定度数的多项式特征组成的特征矩阵:

    • from sklearn.preprocessing import PolynomialFeatures
      # We are simply generating the matrix for a quadratic model
      poly_reg = PolynomialFeatures(degree = 2)
      X_poly = poly_reg.fit_transform(X)
      
    • 接下来,让我们创建一个LinearRegression 对象并将其拟合到我们刚刚生成的特征矩阵 X_poly 中。完全控制特征变量的建模(要设置的指数)。需要精心设计。 需要一些数据知识才能选择最佳指数。

    • # polynomial regression model
      poly_reg_model = LinearRegression()
      poly_reg_model.fit(X_poly, y)
      
支持向量机回归
  • SVM 在回归中的使用称为支持向量回归(SVR)。它对异常值具有鲁棒性,并且在高维空间中有效。Scikit-learn在 SVR()中内置了这种方法。在拟合 SVR 模型之前,通常最好的做法是执行特征缩放,以便每个特征具有相似的重要性。 首先,让我们使用 StandardScaler() 执行特征缩放:

    • from sklearn.svm import SVR
      from sklearn.preprocessing import StandardScaler
      # Performing feature scaling
      scaled_X = StandardScaler()
      scaled_y = StandardScaler()
      scaled_X = scaled_X.fit_transform(X)
      scaled_y = scaled_y.fit_transform(y)
      
    • 接下来,我们创建一个 SVR 对象,内核设置为“rbf”,伽马设置为“auto”。 之后,我们调用 fit() 使其适合缩放的训练数据:

    • svr_regressor = SVR(kernel='rbf', gamma='auto')
      svr_regressor.fit(scaled_X, scaled_y.ravel())
      
决策树回归
  • 目标是创建一个模型,通过学习从数据特征推断出的简单决策规则来预测目标变量的值。 Scikit-learn 将它内置在 DecisionTreeRegressor 中,可以在没有特征缩放的情况下创建 DecisionTreeRegressor 对象
随机森林回归
  • 随机森林回归基本上与决策树回归非常相似。 它是一个元估计器,可以在数据集的各种子样本上拟合多个决策树,并使用平均来提高预测准确性和控制过拟合。Scikit-learn 将它内置在 RandomForestRegressor 中。需要大量计算能力和资源,因为它适合许多决策树来组合它们的输出
  • 组成随机森林的树可以是分类树,也可以是回归树;而GBDT只能由回归树组成。 组成随机森林的树可以并行生成;而GBDT只能是串行生成。 对于最终的输出结果而言,随机森林采用多数投票等;而GBDT则是将所有结果累加起来,或者加权累加起来。
LASSO 回归
  • LASSO 回归是使用收缩的线性回归的变体。收缩是将数据值收缩到中心点作为平均值的过程。这种类型的回归非常适合显示重度多重共线性(特征相互之间高度相关)的模型。它非常适合显示重度多重共线性(特征相互之间高度相关)的模型。LASSO 回归利用 L1 正则化。LASSO 回归被认为比 Ridge 更好,因为它只选择了一些特征并将其他特征的系数降低到零。
岭回归
  • 岭回归与 LASSO 回归非常相似,因为这两种技术都使用了收缩。 Ridge 和 LASSO 回归都非常适合显示重度多重共线性(特征相互之间高度相关)的模型。 它们之间的主要区别在于 Ridge 使用 L2 正则化,这意味着没有一个系数会像 LASSO 回归中那样变为零(而是接近零)。
XGBoost 回归
  • XGBoost 是梯度提升算法的一种高效且有效的实现。梯度提升是指一类可用于分类或回归问题的集成机器学习算法。可以通过创建 XGBRegressor 的实例来定义 XGBoost 模型:

    • from xgboost import XGBRegressor
      # create an xgboost regression model
      model = XGBRegressor(
          n_estimators=1000, 
          max_depth=7, 
          eta=0.1, 
          subsample=0.7, 
          colsample_bytree=0.8,
      )
      model.fit(X, y)
      
      • n_estimators:集成中树的数量,通常会增加,直到看不到进一步的改进。
      • max_depth:每棵树的最大深度,通常值在 1 到 10 之间。
      • eta:用于加权每个模型的学习率,通常设置为较小的值,例如 0.3、0.1、0.01 或更小。
      • subsample:每棵树中使用的样本数,设置为 0 和 1 之间的值,通常为 1.0 以使用所有样本。
      • colsample_bytree:每棵树中使用的特征(列)数,设置为 0 到 1 之间的值,通常为 1.0 以使用所有特征。
    • XGBoost 在稀疏和非结构化数据上表现不佳。

对于树形结构为什么不用归一化
  • 因为数值缩放不影响分裂点位置,对树模型的结构不造成影响。按照特征值进行排序的,排序的顺序不变,那么所属的分支以及分裂点就不会有不同。而且,树模型是不能进行梯度下降的,因为构建树模型(回归树)寻找最优点时是通过寻找最优分裂点完成的,因此树模型是阶跃的,阶跃点是不可导的,并且求导没意义,也就不需要归一化。树型结构不关心变量的值,只关心变量分布以及变量之间的条件概率
bias,variance,error
  • Error = Bias + Variance + Noise,Error反映的是整个模型的准确度,Bias反映的是模型在样本上的输出与真实值之间的误差,即模型本身的精准度,Variance反映的是模型每一次输出结果与模型输出期望之间的误差,即模型的稳定性。
逻辑回归
  • logistic-regression就是一个线性回归经过阶跃函数的处理,变成一个二项分类器,输出结果只能是0,1的条件概率的大小,其实是一种概率模型。

  • 用已知的数据集和训练样本Xi来训练这个模型,从而做到对未知的测试样本进行准确的估计和预测。所以需要对上述公式进行参数估计,求出的W值

    • P ( Y = 1 ∣ x ) = 1 1 + e ( W T x + b ) P(Y=1|x)=\frac{1}{1+e^{(W^Tx+b)}} P(Y=1∣x)=1+e(WTx+b)1

    • 对于逻辑回归而言,其实际就是一个sigmoid函数套上一个回归模型,对于输入X有输出Y属于(0,1),所以只需要对其中的参数进行估计即可,对于参数估计问题,涉及到代价函数,而逻辑回归的代价函数可以用最大似然估计得到。

  • 也就是说,输出 Y=1 的对数几率是由输入 x 的线性函数表示的模型,这就是逻辑回归模型。当 WTx+b 的值越接近正无穷, P(Y=1|x) 概率值也就越接近 1。因此逻辑回归的思路是,先拟合决策边界(不局限于线性,还可以是多项式),再建立这个边界与分类的概率联系,从而得到了二分类情况下的概率

  • 逻辑回归与线性回归都属于广义线性回归模型, 逻辑回归处理的是分类问题,线性回归处理的是回归问题,这是两者最本质的区别。线性回归中使用的是最小化平方误差损失函数(线性回归就是y=WTx+b,损失函数用MSE)

  • 极大似然估计法: 就是利用已知的样本结果信息,反推最具有可能(最大概率)导致这些样本结果出现的模型参数值!那么既然事情已经发生了,为什么不让这个出现的结果的可能性最大呢?这也就是最大似然估计的核心。白球黑球不知道有多少,取100次有放回,70是白,30黑,那么采取的方法是让这个样本结果出现的可能性最大,也就是使得p70(1-p)30值最大,那么我们就可以看成是p的方程,求导即可!50,50。20,80等无数种组合都可以,为什么要70和30呢?因为是已经发生的事情了,就让他作为可能性最大的结果。

逻辑回归处理多分类标签问题
  • 如果一个样本只对应于一个标签,我们可以假设每个样本属于不同标签的概率服从于几何分布,使用多项逻辑回归( Softmax Regression ) 来进行分类。当存在样本可能居于多个标签的情况时,我们可以训练 k个二分类的逻辑回归分类器。第i个分类器用以区分每个样本是否可以归为第i类,训练该分类器时,需要把标签重新整理为“第 i 类标签” 与“非第i类标签”两类。 遇过这样的办法,我们就解决了每个样本可能拥有多个标签的情况。
朴素贝叶斯模型
  • 条件概率: P ( A ∣ B ) = P ( A B ) P ( B ) P(A|B)=\frac{P(AB)}{P(B)} P(AB)=P(B)P(AB); P ( B ∣ A ) = P ( A B ) P ( A ) P(B|A)=\frac{P(AB)}{P(A)} P(BA)=P(A)P(AB);所以有 P ( A B ) = P ( A ∣ B ) ∗ P ( B ) = P ( B ∣ A ) ∗ P ( B ) P(AB)=P(A|B)*P(B)=P(B|A)*P(B) P(AB)=P(AB)P(B)=P(BA)P(B)

  • 所以贝叶斯公式为 P ( A ∣ B ) = P ( B ∣ A ) ∗ P ( A ) P ( B ) P(A|B)=\frac{P(B|A)*P(A)}{P(B)} P(AB)=P(B)P(BA)P(A)

  • 全概率公式 P ( A ) = ∑ i = 1 n P ( A B i ) P(A)=\sum_{i=1}^nP(AB_i) P(A)=i=1nP(ABi),且条件概率替换 P ( A ) = ∑ i = 1 n P ( A ∣ B i ) P ( B i ) P(A)=\sum_{i=1}^nP(A|B_i)P(B_i) P(A)=i=1nP(ABi)P(Bi)

  • 朴素贝叶斯为什么“朴素naive”, 因为分母对于所有类别为常数,我们只要将分子最大化即可。又因为各特征属性是条件独立的(朴素贝叶斯为什么“朴素”的原因),

朴素贝叶斯的工作流程
  • 对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。通俗来说,就好比这么个道理,你在街上看到一个黑人,我问你你猜这哥们哪里来的,你十有八九猜非洲。为什么呢?因为黑人中非洲人的比率最高,当然人家也可能是美洲人或亚洲人,但在没有其它可用信息下,我们会选择条件概率最大的类别,这就是朴素贝叶斯的思想基础。
集成学习
  • 目前常见的集成学习算法主要有2种:基于Bagging的算法和基于Boosting的算法,基于Bagging的代表算法有随机森林,而基于Boosting的代表算法则有Adaboost、GBDT、XGBOOST等。集成学习框架,主流的有三,Bagging(并行),Boosting(串行),Stacking。

  • bagging:多次采样(bootstrap (有放回的随机抽样)每次从训练集中抽取一个固定大小的训练集A,随机重抽样),训练多个分类器,集体投票,旨在减小方差。如果是分类算法预测,则T个弱学习器投出最多票数的类别或者类别之一为最终类别。如果是回归算法,T个弱学习器得到的回归结果进行算术平均得到的值为最终的模型输出。常用bagging算法:随机森林算法。

  • boosting:基分类器层层叠加,聚焦分错的样本,旨在减小方差涉及到两个部分,加法模型和前向分步算法。加法模型就是说强分类器由一系列弱分类器线性相加而成。前向分步就是说在训练过程中,下一轮迭代产生的分类器是在上一轮的基础上训练得来的。他是一种框架算法,主要是通过对样本集的操作获得样本子集,然后用弱分类算法在样本子集上训练生成一系列的基分类器。他可以用来提高其他弱分类算法的识别率,也就是将其他的弱分类算法作为基分类算法放于Boosting 框架中,通过Boosting框架对训练样本集的操作,得到不同的训练样本子集,用该样本子集去训练生成基分类器;每得到一个样本集就用该基分类算法在该样本集上产生一个基分类器,这样在给定训练轮数 n 后,就可产生 n 个基分类器,然后Boosting框架算法将这 n个基分类器进行加权融合,产生一个最后的结果分类器

  • Boosting是一种与Bagging很类似的技术。它的基本原理:先从初始训练集训练出一个基学习器,再根据基学习器的表现对训练样本分布进行调整,提高被错误分类的样本的权重降低被正确分类的样本的权重使得先前基学习器做错的训练样本在后续受到更多的关注,然后基于调整后的样本分布来训练下一个基学习器;如此重复进行,直至基学习器数目达到事先指定的值T,最后将这T个基学习器进行加权结合。

  • stacking:多次采样,训练多个分类器,将输出作为最后的输入特征, 由k-NN、随机森林和朴素贝叶斯基础分类器组成,它的预测结果由作为元分类器的Loqistic 回归组合。

Adaboost原理
  • 它的自适应在于:前一个基本分类器被错误分类的样本的权值会增大,而正确分类的样本的权值会减小,并再次用来训练下一个基本分类器。同时,在每一轮迭代中,加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数才确定最终的强分类器

  • Gradient Boost Decision Tree。总共构建T棵树。当构建到第t棵树的时候,需要对前t-1棵树的训练样本分类回归产生的残差进行拟合。每次构建树的方式以及数据集一样,只不过拟合的目标变成了t-1棵树输出的残差。不可并行化处理。GBDT是一种boosting算法。

  • Adaboost如何用于分类:

  • 计算样本权重:训练数据中的每个样本,赋予其权重,即样本权重,用向量D表示,这些权重都初始化成相等值。假设有n个样本的训练集,设定每个样本的权重都是相等的,即1/n

  • 计算错误率:利用第一个弱学习算法h1对其进行学习,学习完成后进行错误率ε的统计;计算弱学习算法权重:弱学习算法也有一个权重,用向量α表示,利用错误率计算权重α:α>0,错误率<0.5, 错误率越小,α越大。错误率=0.5,α=1;α<0:错误率很大的时候;

  • 更新样本权重:在第一次学习完成后,需要重新调整样本的权重,以使得在第一分类中被错分的样本的权重,在接下来的学习中可以重点对其进行学习;其中,h(xi)=yi表示对第i个样本训练正确,不等于则表示分类错误。Z是一个归一化因子:Zt=sum(D)

  • 重复进行学习,这样经过t轮的学习后,就会得到t个弱学习算法、权重、弱分类器的输出以及最终的AdaBoost算法的输出:H(X)>0 是1类;H(X)<0 是-1类

为什么LR适合处理高维稀疏特征,而GBDT不适合
  • 高维稀疏特征的时候,使用 gbdt 很容易过拟合。带正则化的线性模型比较不容易对稀疏特征过拟合。从高维稀疏特征中难以进行有效的特征空间划分,且对噪音会很敏感。
Python中的 @staticmethod@classmethod方法
  • Python面向对象编程中,类中定义的方法可以是 @classmethod 装饰的类方法,也可以是 @staticmethod 装饰的静态方法,用的最多的还是不带装饰器的实例方法,如果把这几个方法放一块,对初学者来说无疑是一头雾水,那我们该如何正确地使用它们呢?

  • class A(object):
        def m1(self, n):
            print("self:", self)
        @classmethod
        def m2(cls, n):
            print("cls:", cls)
        @staticmethod
        def m3(n):
            pass
    a = A()
    a.m1(1) # self: <__main__.A object at 0x00000166EB8313D0>
    A.m2(1) # cls: <class '__main__.A'>
    A.m3(1)
    
  • 在类中一共定义了3个方法,m1 是实例方法,第一个参数必须是 self(约定俗成的)。m2 是类方法,第一个参数必须是cls(同样是约定俗成),m3 是静态方法,参数根据业务需求定,可有可无。当程序运行时,大概发生了这么几件事(结合下面的图来看)。

    • 第一步:代码从第一行开始执行 class 命令,此时会创建一个类 A 对象(没错,类也是对象,一切皆对象嘛)同时初始化类里面的属性和方法,记住,此刻实例对象还没创建出来。

    • 第二、三步:接着执行 a=A(),系统自动调用类的构造器,构造出实例对象 a

    • 第四步:接着调用 a.m1(1) ,m1 是实例方法,内部会自动把实例对象传递给 self 参数进行绑定,也就是说, self 和 a 指向的都是同一个实例对象。

    • 第五步:调用A.m2(1)时,python内部隐式地把类对象传递给 cls 参数,cls 和 A 都指向类对象。

    • 在这里插入图片描述

    • 严格意义上来说,左边的都是变量名,是对象的引用,右边才是真正的对象,为了描述方便,我直接把 a 称为对象,你应该明白我说对象其实是它所引用右边的那个真正的对象。正确理解Python中的 @staticmethod@classmethod方法 - 知乎 (zhihu.com)

  • 实例方法

    • print(A.m1)
      # A.m1在py2中显示为<unbound method A.m1>
      <function A.m1 at 0x00000166EB812EE0>
      print(a.m1)
      <bound method A.m1 of <__main__.A object at 0x00000166EB8313D0>>
      
    • A.m1是一个还没有绑定实例对象的方法,对于未绑定方法,调用 A.m1 时必须显示地传入一个实例对象进去,而 a.m1是已经绑定了实例的方法,python隐式地把对象传递给了self参数,所以不再手动传递参数,这是调用实例方法的过程

    • A.m1(a, 1)
      # 等价  
      a.m1(1)
      
    • 如果未绑定的方法 A.m1 不传实例对象给 self 时,就会报参数缺失错误,在 py3 与 py2 中,两者报的错误不一致,python2 要求第一个参数self是实例对象,而python3中可以是任意对象。

    • A.m1(1)
      ## TypeError: m1() missing 1 required positional argument: 'n'
      
  • 类方法

    • print(A.m2)
      print(a.m2) 
      <bound method A.m2 of <class '__main__.A'>>
      <bound method A.m2 of <class '__main__.A'>>
      
    • m2是类方法,不管是 A.m2 还是 a.m2,都是已经自动绑定了类对象A的方法,对于后者,因为python可以通过实例对象a找到它所属的类是A,找到A之后自动绑定到 cls。这使得我们可以在实例方法中通过使用 self.m2()这种方式来调用类方法和静态方法

  • 静态方法

    • print(A.m3)
      print(a.m3) 
      <function A.m3 at 0x00000166EB8600D0>
      <function A.m3 at 0x00000166EB8600D0>
      
    • m3是类里面的一个静态方法,跟普通函数没什么区别,与类和实例都没有所谓的绑定关系,它只不过是碰巧存在类中的一个函数而已。不论是通过类还是实例都可以引用该方法。

  • 应用场景

    • 静态方法的使用场景:如果在方法中不需要访问任何实例方法和属性,纯粹地通过传入参数并返回数据的功能性方法,那么它就适合用静态方法来定义,它节省了实例化对象的开销成本,往往这种方法放在类外面的模块层作为一个函数存在也是没问题的,而放在类中,仅为这个类服务。staticmethod相当于定义了一个局部域函数为该类专门服务

    • 类方法的使用场景有:作为工厂方法创建实例对象,例如内置模块 datetime.date 类中就有大量使用类方法作为工厂方法,以此来创建date对象。

      • class date:
            def __new__(cls, year, month=None, day=None):
                self = object.__new__(cls)
                self._year = year
                self._month = month
                self._day = day
                return self
            @classmethod
            def fromtimestamp(cls, t):
                y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
                return cls(y, m, d)
            @classmethod
            def today(cls):
                t = _time.time()
                return cls.fromtimestamp(t)
        
  • 为了实现一个静态类,我们可以将它的方法和变量设为静态。为此,我们可以使用@staticmethod 装饰器在静态类中创建方法。装饰器是在函数之前指定的特殊函数,并将整个函数作为参数。

  • @classmethod 可以使类的方法静态化,而不是其对象的静态方法。与@staticmethod 装饰器相比,它有几个优点。它还可以与子类一起使用并可以修改类状态。它需要在名为 cls 的方法中包含一个强制参数。

  • staticmethod用于修饰类中的方法,使其可以在不创建类实例的情况下调用方法,这样做的好处是执行效率比较高。当然,也可以像一般的方法一样用实例调用该方法。该方法一般被称为静态方法。静态方法不可以引用类中的属性或方法,其参数列表也不需要约定的默认参数self。我个人觉得,静态方法就是类对外部函数的封装,有助于优化代码结构和提高程序的可读性。当然了,被封装的方法应该尽可能的和封装它的类的功能相匹配。
    法。装饰器是在函数之前指定的特殊函数,并将整个函数作为参数。

  • @classmethod 可以使类的方法静态化,而不是其对象的静态方法。与@staticmethod 装饰器相比,它有几个优点。它还可以与子类一起使用并可以修改类状态。它需要在名为 cls 的方法中包含一个强制参数。

  • staticmethod用于修饰类中的方法,使其可以在不创建类实例的情况下调用方法,这样做的好处是执行效率比较高。当然,也可以像一般的方法一样用实例调用该方法。该方法一般被称为静态方法。静态方法不可以引用类中的属性或方法,其参数列表也不需要约定的默认参数self。我个人觉得,静态方法就是类对外部函数的封装,有助于优化代码结构和提高程序的可读性。当然了,被封装的方法应该尽可能的和封装它的类的功能相匹配。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羞儿

写作是兴趣,打赏看心情

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值