Lesson 4.1 逻辑回归模型构建与多分类学习方法

首先我们来讨论关于逻辑回归的基本原理,当然,在此过程中,我们也将进一步补充机器学习数学理论基础。

逻辑回归的基本原理,从整体上来划分可以分为两个部分,其一是关于模型方程的构建,也就是方程的基本形态,当然也包括模型的基本性质及其结果解读;其二则是模型参数求解,即在构建完模型之后如何利用数学工具求解最佳参数。而这两部分其实都可以从多个角度出发进行理解,基本划分情况如下

  • 模型构建部分:可以从广义线性回归(Generalized liner model)+对数几率函数(logit function)角度理解,也可以从随机变量的逻辑斯蒂分布(logistic distribution)角度出发进行理解;
  • 参数求解部分:可以借助极大似然估计(Maximum Likelihood Estimate)方法求解,可以借助KL离散度基本理论构建二分类交叉熵损失函数求解。
    而无论这些基础理论难易程度如何,其对于此后的机器学习都是至关重要的,因此课上将先从简单角度出发,先构建对逻辑回归基本理论体系的完整认知,然后再补充更加复杂的理论体系,为后续其他算法的学习做铺垫。

本节我们将先讨论关于逻辑回归的模型构建部分,同时也将讨论模型结果解读和模型可解释性的相关内容,下一节我们将具体讨论关于模型参数求解的相关内容。

# 科学计算模块
import numpy as np
import pandas as pd# 绘图模块
import matplotlib as mpl
import matplotlib.pyplot as plt# 自定义模块
from ML_basic_function import *

一、广义线性模型(Generalized liner model)的基本定义

在Lesson3中我们曾谈到关于线性回归的局限性,这种局限性的根本由模型本身的简单线性结构(自变量加权求和预测因变量)导致的。如果说线性回归是在一个相对严格的条件下建立的简单模型,那么在后续实践应用过程中,人们根据实际情况的不同,在线性回归的基础上又衍生出了种类繁多的线性类模型。其中,有一类线性模型,是在线性回归基础上,在等号的左边或右边加上了一个函数,从而能够让模型更好的捕捉一般规律,此时该模型就被称为广义线性模型,该函数就被称为联系函数。

广义线性模型的提出初衷上还是为了解决非线性相关的预测问题,例如,现在有数据分布如下:

# 数据集特征
np.random.seed(24)
x = np.linspace(0, 4, 20).reshape(-1, 1)
x = np.concatenate((x, np.ones_like(x)), axis=1)
x
#array([[0.        , 1.        ],
#       [0.21052632, 1.        ],
#       [0.42105263, 1.        ],
#       [0.63157895, 1.        ],
#       [0.84210526, 1.        ],
#       [1.05263158, 1.        ],
#       [1.26315789, 1.        ],
#       [1.47368421, 1.        ],
#       [1.68421053, 1.        ],
#       [1.89473684, 1.        ],
#       [2.10526316, 1.        ],
#       [2.31578947, 1.        ],
#       [2.52631579, 1.        ],
#       [2.73684211, 1.        ],
#       [2.94736842, 1.        ],
#       [3.15789474, 1.        ],
#       [3.36842105, 1.        ],
#       [3.57894737, 1.        ],
#       [3.78947368, 1.        ],
#       [4.        , 1.        ]])
# 数据集标签
y = np.exp(x[:, 0] + 1).reshape(-1, 1)
y
#array([[  2.71828183],
#       [  3.35525011],
#       [  4.1414776 ],
#       [  5.11193983],
#       [  6.30980809],
#       [  7.78836987],
#       [  9.61339939],
#       [ 11.86608357],
#       [ 14.64663368],
#       [ 18.07874325],
#       [ 22.31509059],
#       [ 27.54413077],
#       [ 33.99847904],
#       [ 41.96525883],
#       [ 51.79887449],
#       [ 63.93677707],
#       [ 78.91892444],
#       [ 97.41180148],
#       [120.23806881],
#       [148.4131591 ]])

此时x和y的真实关系为y=e(x+1)y=e^{(x+1)}y=e(x+1)但如果以线性方程来进行预测,即:
y=wT⋅x+by= w^T \cdot x + by=wT⋅x+b
当然,我们可以令w^=[w1,w2,...wd,b]T\hat w = [w_1,w_2,...w_d, b]^Tw^=[w1​,w2​,...wd​,b]T,x^=[x1,x2,...xd,1]T\hat x = [x_1,x_2,...x_d, 1]^Tx^=[x1​,x2​,...xd​,1]T,从而将上述方程改写为:
y=w^T⋅x^y= \hat w^T \cdot \hat xy=w^T⋅x^
则模型输出结果为:

np.linalg.lstsq(x, y, rcond=-1)[0]
#array([[ 30.44214742],
#       [-22.37576724]])

即y=30.44x−22.38y=30.44x-22.38y=30.44x−22.38
则模型预测结果为:

yhat = x[:, 0] * 30.44 - 22.38
yhat
#array([-22.38      , -15.97157895,  -9.56315789,  -3.15473684,
#         3.25368421,   9.66210526,  16.07052632,  22.47894737,
#        28.88736842,  35.29578947,  41.70421053,  48.11263158,
#        54.52105263,  60.92947368,  67.33789474,  73.74631579,
#        80.15473684,  86.56315789,  92.97157895,  99.38      ])
# 观察模型预测和真实结果
plt.plot(x[:, 0], y, 'o')
plt.plot(x[:, 0], yhat, 'r-')


能够发现,线性模型预测结果和真实结果差距较大。但此时如果我们在等号右边加上以eee为底的指数运算,也就是将线性方程输出结果进行以eee为底的指数运算转换之后去预测y,即将方程改写为y=e(w^T⋅x^)y=e^{(\hat w^T \cdot \hat x)}y=e(w^T⋅x^)
等价于
lny=w^T⋅x^lny = \hat w^T \cdot \hat xlny=w^T⋅x^
即相当于是线性方程输出结果去预测yyy取以eee为底的对数运算之后的结果
此时我们可以带入lnylnylny进行建模

np.linalg.lstsq(x, np.log(y), rcond=-1)[0]
#array([[1.],
#       [1.]])

可得到方程lny=x+1lny=x+1lny=x+1等价于y=e(x+1)y=e^{(x+1)}y=e(x+1)即解出原方程。

通过上面的过程,我们不难发现,通过在模型左右两端加上某些函数,能够让线性模型也具备捕捉非线性规律的能力。而在上例中,这种捕捉非线性规律的本质,是在方程加入lnlnln对数函数之后,能够使得模型的输入空间(特征所在空间)到输出空间(标签所在空间)进行了非线性的函数映射。而这种连接线性方程左右两端、并且实际上能够拓展模型性能的函数,就被称为联系函数,而加入了联系函数的模型也被称为广义线性模型。广义线性模型的一般形式可表示如下:
g(y)=w^T⋅x^g(y)=\hat w^T \cdot \hat xg(y)=w^T⋅x^
等价于y=g−1(w^T⋅x^)y = g^{-1}(\hat w^T \cdot \hat x)y=g−1(w^T⋅x^)
其中g(⋅)g(·)g(⋅)为联系函数(link function),g−1(⋅)g^{-1}(·)g−1(⋅)为联系函数的反函数(如y=ex与ln(y)=xy=e^x与ln(y)=xy=ex与ln(y)=x)。而如上例中的情况,也就是当联系函数为自然底数的对数函数时,该模型也被称为对数线性模型(logit linear model)。

注:一般来说广义线性模型要求联系函数必须是单调可微函数。

从广义线性模型的角度出发,当联系函数为g(x)=xg(x)=xg(x)=x时,g(y)=y=w^T⋅x^g(y)=y=\hat w^T \cdot \hat xg(y)=y=w^T⋅x^,此时就退化成了线性模型。而能够通过联系函数拓展模型捕捉规律的范围,这也就是广义的由来。

二、对数几率模型与逻辑回归

逻辑回归也被称为对数几率回归。接下来,我们从广义线性模型角度理解逻辑回归。

1.对数几率模型(logit model)

  • 几率(odd)与对数几率
      几率不是概率,而是一个事件发生与不发生的概率的比值。假设某事件发生的概率为p,则该事件不发生的概率为1-p,该事件的几率为:
    odd(p)=p1−podd(p)=\frac{p}{1-p}odd(p)=1−pp​
    在几率的基础上取(自然底数的)对数,则构成该事件的对数几率(logit):
    logit(p)=lnp1−plogit(p) = ln\frac{p}{1-p}logit(p)=ln1−pp​

注,logit的是log unit对数单元的简写,和中文中的“逻辑”一词并没有关系。对数几率模型也被称为对数单位模型(log unit model)。

  • 对数几率模型

如果我们将对数几率看成是一个函数,并将其作为联系函数,即g(y)=lny1−yg(y)=ln\frac{y}{1-y}g(y)=ln1−yy​,则该广义线性模型为:
g(y)=lny1−y=w^T⋅x^g(y)=ln\frac{y}{1-y}=\hat w^T \cdot \hat xg(y)=ln1−yy​=w^T⋅x^
此时模型就被称为对数几率回归(logistic regression),也被称为逻辑回归。

国内很多学者认为,logistic regression一词和逻辑的含义相差甚远,将其译为逻辑回归并不妥当。课上不对逻辑回归和对数几率回归进行译名是否妥当的讨论。

数理统计分析方法构建逻辑回归时,基本假设要求变量y必须服从伯努利分布(Bernoulli)。

2.逻辑回归与Sigmoid函数

  • 对数几率函数与Sigmoid函数
    当然,更进一步的,如果我们希望将上述对数几率函数“反解”出来,也就是改写为y=f(x)y=f(x)y=f(x)形式,则可参照下述形式:

方程左右两端取自然底数:
y1−y=ew^T⋅x^\frac{y}{1-y}=e^{\hat w^T \cdot \hat x}1−yy​=ew^T⋅x^
方程左右两端+1可得:
y+(1−y)1−y=11−y=ew^T⋅x^+1\frac{y+(1-y)}{1-y}=\frac{1}{1-y}=e^{\hat w^T \cdot \hat x}+11−yy+(1−y)​=1−y1​=ew^T⋅x^+1
方程左右两端取倒数可得:
1−y=1ew^T⋅x^+11-y=\frac{1}{e^{\hat w^T \cdot \hat x}+1}1−y=ew^T⋅x^+11​
1-方程左右两端可得:
y=1−1ew^T⋅x^+1=ew^T⋅x^ew^T⋅x^+1=11+e−(w^T⋅x^)=g−1(w^T⋅x^)\begin{aligned} y &= 1-\frac{1}{e^{\hat w^T \cdot \hat x}+1}\\ &=\frac{e^{\hat w^T \cdot \hat x}}{e^{\hat w^T \cdot \hat x}+1} \\ &=\frac{1}{1+e^{-(\hat w^T \cdot \hat x)}} = g^{-1}(\hat w^T \cdot \hat x) \end{aligned}y​=1−ew^T⋅x^+11​=ew^T⋅x^+1ew^T⋅x^​=1+e−(w^T⋅x^)1​=g−1(w^T⋅x^)​
因此,逻辑回归基本模型方程为:
y=11+e−(w^T⋅x^)y = \frac{1}{1+e^{-(\hat w^T \cdot \hat x)}}y=1+e−(w^T⋅x^)1​

同时我们也能发现,对对数几率函数的反函数为:
f(x)=11+e−xf(x) = \frac{1}{1+e^{-x}}f(x)=1+e−x1​
我们可以简单观察该函数的函数图像:

np.random.seed(24)
x = np.linspace(-10, 10, 100)
y = 1 / (1 + np.exp(-x))plt.plot(x, y)


能够看出该函数的图像近似S形,这种类似S形的函数,也被称为Sigmoid函数。

注:Sigmoid严格定义是指形如S型的函数,并不是特指某个函数,也就是说,从严格意义来讨论,函数f(x)=11+e−xf(x) = \frac{1}{1+e^{-x}}f(x)=1+e−x1​只能被称为是Sigmoid函数的一种。但实际上,由于该函数是最著名且通用的Sigmoid函数,因此大多数时候,我们在说Sigmoid函数的时候,其实就是在指f(x)=11+e−xf(x) = \frac{1}{1+e^{-x}}f(x)=1+e−x1​函数。后续课上对该概念不做区分,Sigmoid函数即指f(x)=11+e−xf(x) = \frac{1}{1+e^{-x}}f(x)=1+e−x1​函数。

3.Sigmoid函数性质

  • Sigmoid函数性质与一阶导函数
      对于Sigmoid函数来说,函数是单调递增函数,并且自变量在实数域上取值时,因变量取值范围在(0,1)之间。并且当自变量取值小于0时,因变量取值小于0.5,当自变量取值大于0时,因变量取值大于0.5。
      并且,我们简单查看Sigmoid导函数性质。
    令:
    Sigmoid(x)=11+e−xSigmoid(x) = \frac{1}{1+e^{-x}}Sigmoid(x)=1+e−x1​
    对其求导可得:
    Sigmoid′(x)=(11+e−x)′=((1+e−x)−1)′=(−1)(1+e−x)−2⋅(e−x)′=(1+e−x)−2(e−x)=e−x(1+e−x)2=e−x+1−1(1+e−x)2=11+e−x−1(1+e−x)2=11+e−x(1−11+e−x)=Sigmoid(x)(1−Sigmoid(x))\begin{aligned} Sigmoid'(x) &= (\frac{1}{1+e^{-x}})' \\ &=((1+e^{-x})^{-1})' \\ &=(-1)(1+e^{-x})^{-2} \cdot (e^{-x})' \\ &=(1+e^{-x})^{-2}(e^{-x}) \\ &=\frac{e^{-x}}{(1+e^{-x})^{2}} \\ &=\frac{e^{-x}+1-1}{(1+e^{-x})^{2}} \\ &=\frac{1}{1+e^{-x}} - \frac{1}{(1+e^{-x})^2} \\ &=\frac{1}{1+e^{-x}}(1-\frac{1}{1+e^{-x}}) \\ &=Sigmoid(x)(1-Sigmoid(x)) \end{aligned}Sigmoid′(x)​=(1+e−x1​)′=((1+e−x)−1)′=(−1)(1+e−x)−2⋅(e−x)′=(1+e−x)−2(e−x)=(1+e−x)2e−x​=(1+e−x)2e−x+1−1​=1+e−x1​−(1+e−x)21​=1+e−x1​(1−1+e−x1​)=Sigmoid(x)(1−Sigmoid(x))​
    我们发现,Sigmoid函数的导函数可以简单的用Sigmoid函数本身来表示。接下来我们验证Sigmoid导函数特性,首先简单定义Sigmoid函数:
def sigmoid(x):return (1 / (1 + np.exp(-x)))
sigmoid(10)
#0.9999546021312976

据此可定义Sigmoid导函数的函数:

def sigmoid_deri(x):return (sigmoid(x)*(1-sigmoid(x)))
sigmoid_deri(10)
#4.5395807735907655e-05

进一步,我们可以绘制Sigmoid导函数图像:

plt.plot(x, sigmoid_deri(x))


我们发现,Sigmoid导函数在实数域上取值大于0,并且函数图像先递增后递减,并在0点取得最大值。据此我们也可以进一步讨论Sigmoid函数性质:

plt.plot(x, sigmoid(x))


由于导函数始终大于0,因此Sigmoid函数始终递增,并且导函数在0点取得最大值,因此Sigmoid在0点变化率最快,而在远离零点的点,Sigmoid导函数取值较小,因此该区间Sigmoid函数变化缓慢。该区间也被称为Sigmoid的饱和区间。

当然,如果从简单探索Sigmoid函数的二阶导函数,其实能够发现,x<0时二阶导函数取值大于0(一阶导函数递增),而x>0时二阶导函数小于0(一阶导函数递减)。因此0点其实也是sigmoid函数的拐点。

函数拐点指的是二阶导函数左右异号的点,从凹凸性来看就是函数凹凸性发生变化的点。

总结sigmoid函数性质如下:

三、逻辑回归模型输出结果与模型可解释性

从整体情况来看,逻辑回归在经过Sigmoid函数处理之后,是将线性方程输出结果压缩在了0-1之间,用该结果再来进行回归类的连续数值预测肯定是不合适的了。在实际模型应用过程中,逻辑回归主要应用于二分类问题的预测。

一般来说,我们会将二分类的类别用一个两个分类水平取值的离散变量来代表,两个分类水平分别为0和1。该离散变量也被称为0-1离散变量。

  • 连续型输出结果转化为分类预测结果

对于逻辑回归输出的(0,1)之间的连续型数值,我们只需要确定一个“阈值”,就可以将其转化为二分类的类别判别结果。通常来说,这个阈值是0.5,即以0.5为界,调整模型输出结果:
ycla={0,y<0.51,y≥0.5y_{c l a}=\left\{\begin{array}{l} 0, y<0.5 \\ 1, y \geq 0.5 \end{array}\right. ycla​={0,y<0.51,y≥0.5​
其中,yclay_{cla}ycla​为类别判别结果,而yyy为逻辑回归方程输出结果sigmoid(w^T⋅x^)sigmoid(\hat w^T \cdot \hat x)sigmoid(w^T⋅x^)。例如,有简单数据集如下:

由于只有一个自变量,因此可假设逻辑回归模型如下:
y=11+ex−1y = \frac{1}{1+e^{x-1}} y=1+ex−11​
带入数据可进一步计算模型输出结果:

x = np.array([2, 0.5]).reshape(-1, 1)
sigmoid(1-x)
#array([[0.26894142],
#       [0.62245933]])

据此,在阈值为0.5的情况下,模型会将第一条判别为0,第二条结果判别为1,上述过程代码实现如下:

yhat = sigmoid(1-x)                 # 模型预测结果
yhat
#array([[0.26894142],
#       [0.62245933]])
ycla = np.zeros_like(yhat)
ycla                               # 类别判别结果
#array([[0.],
#       [0.]])
thr = 0.5                         # 设置阈值
yhat >= thr                       # 数组判别
#array([[False],
#       [ True]])
ycla[yhat >= thr] = 1            # 布尔索引
ycla
#array([[0.],
#       [1.]])

即:

当然,我们也可以将该过程封装为一个函数:

def logit_cla(yhat, thr=0.5):"""逻辑回归类别输出函数::param yhat: 模型输出结果:param thr:阈值:return ycla:类别判别结果"""ycla = np.zeros_like(yhat)ycla[yhat >= thr] = 1return ycla

测试函数性能:

logit_cla(yhat)
#array([[0.],
#       [1.]])

关于阈值的选取与0\1分类的类别标记:阈值为人工设置的参数,在没有特殊其他要求下,一般取值为0.5。而关于类别的数值转化,即将哪一类设置为0哪一类设置为1,也完全可以由人工确定,一般来说,我们会将希望被判别或被识别的类设置为1,例如违约客户、确诊病例等。

  • 逻辑回归输出结果(y)是否是概率

决定y是否是概率的核心因素,不是模型本身,而是建模流程。

逻辑斯蒂本身也有对应的概率分布,因此输入的自变量其实是可以视作随机变量的,但前提是需要满足一定的分布要求。如果逻辑回归的建模流程遵照数理统计方法的一般建模流程,即自变量的分布(或者转化之后的分布)满足一定要求(通过检验),则最终模型输出结果就是严格意义上的概率取值。而如果是遵照机器学习建模流程进行建模,在为对自变量进行假设检验下进行模型构建,则由于自变量分布不一定满足条件,因此输出结果不一定为严格意义上的概率。

而课上我们基本都采用机器学习建模流程进行逻辑回归的构建,因此对于模型输出结果y,其实并不一定是严格意义上的概率。不过在目前大多数使用场景中,由于大家希望能够用到模型本身的可解释性,因此还是会将模型结果解读为1发生的概率。尽管这并不是一个严谨的做法,但在机器学习整体的“实证”倾向下,只要业务方接受这种做法、并且能够一定程度指导业务,我们就可以将其解读为概率。 课上我们将逻辑回归输出结果看成近似概率值。

例如在上例中:

我们可以说,第一条样本预测为1的概率为0.27,相比属于类别1,第一条样本更大概率属于类别0;而第二条样本属于类别1的概率高达62%,因此第二条样本我们判别其属于类别1。

并且,根据逻辑回归方程:
y=11+e−(1−x)y = \frac{1}{1+e^{-(1-x)}} y=1+e−(1−x)1​
可以进一步推导出:
lny1−y=1−xln\frac{y}{1-y} = 1-xln1−yy​=1−x
可解读为x每增加1,样本属于1的概率的对数几率就减少1。(此处应是减少,请注意)

当然,类似的可解释性,也就是自变量变化对因变量变化的贡献程度的解读,对于线性回归同样适用。例如

Lesson 4.1-4.2 逻辑回归模型构建与多分类学习方法逻辑回归参数估计相关推荐

  1. keras构建前馈神经网络(feedforward neural network)进行回归模型构建和学习

    keras构建前馈神经网络(feedforward neural network)进行回归模型构建和学习 我们不必在"回归"一词上费太多脑筋.英国著名统计学家弗朗西斯·高尔顿(Fr ...

  2. R语言使用R基础安装中的glm函数构建乳腺癌二分类预测逻辑回归模型、分类预测器(分类变量)被自动替换为一组虚拟编码变量、summary函数查看检查模型、使用table函数计算混淆矩阵评估分类模型性能

    R语言使用R基础安装中的glm函数构建乳腺癌二分类预测逻辑回归模型(Logistic regression).分类预测器(分类变量)被自动替换为一组虚拟编码变量.summary函数查看检查模型.使用t ...

  3. 逻辑回归模型_联邦学习体系下——逻辑回归模型

    联邦学习的体系我们在前期介绍过,这里我们简单回顾一下纵向联邦学习的定义:在两个数据集的用户重叠较多而用户特征重叠较少的情况下,将数据集按照纵向 (即特征维度)切分,并取出双方用户相同而用户特征不完全相 ...

  4. R语言回归模型构建、回归模型基本假设(正态性、线性、独立性、方差齐性)、回归模型诊断、car包诊断回归模型、特殊观察样本分析、数据变换、模型比较、特征筛选、交叉验证、预测变量相对重要度

    R语言回归模型构建.回归模型基本假设(正态性.线性.独立性.方差齐性).回归模型诊断.car包诊断回归模型.特殊观察样本分析.数据变换.模型比较.特征筛选.交叉验证.预测变量相对重要度 目录

  5. R语言rpartb包树回归模型构建:基于前列腺prostate数据集

    R语言rpartb包树回归模型构建:基于前列腺prostate数据集 决策树是一种机器学习的方法.决策树的生成算法有ID3, C4.5和C5.0等.决策树是一种树形结构,其中每个内部节点表示一个属性上 ...

  6. R语言rpartb包树回归模型构建:基于乳腺癌(breast cancer)数据集

    R语言rpartb包树回归模型构建:基于乳腺癌(breast cancer)数据集 目录 R语言rpartb包树回归模型构建:基于乳腺癌(breast cancer)数据集

  7. R语言广义线性模型函数GLM、glm函数构建泊松回归模型(Poisson regression)、泊松回归模型系数解读、查看系数的乘法效应(Interpreting the model para)

    R语言广义线性模型函数GLM.glm函数构建泊松回归模型(Poisson regression).泊松回归模型系数解读.查看系数的乘法效应(Interpreting the model paramet ...

  8. R语言glmnet拟合lasso回归模型实战:lasso回归模型的模型系数及可视化、lasso回归模型分类评估计算(混淆矩阵、accuracy、Deviance)

    R语言glmnet拟合lasso回归模型实战:lasso回归模型的模型系数(lasso regression coefficients)及可视化.lasso回归模型分类评估计算(混淆矩阵.accura ...

  9. 门限回归模型的思想_Stata+R:门槛回归教程

    来源 | 数量经济学综合整理 转载请联系 进行回归分析,一般需要研究系数的估计值是否稳定.很多经济变量都存在结构突变问题,使用普通回归的做法就是确定结构突变点,进行分段回归.这就像我们高中学习的分段函 ...

最新文章

  1. 下一个人才大缺口:量子计算研究人员
  2. 赤兔四足机器人的作用_腾讯 Robotics X 实验室四足移动机器人Jamoca首亮相,可挑战高难度梅花桩...
  3. XcodeGhost风波过后,苹果如何防范风险?
  4. 使用python+ffmpeg批量转换格式
  5. 声明式事务基于注解@Transactional的理解
  6. Gym 100090D Insomnia
  7. 安卓APP_ Fragment(3)—— Fragment的生命周期
  8. 【CSU - 1980 】不堪重负的树(树上区间dp)
  9. Notification使用详解之三:通过服务更新进度通知在Activity中监听服务进度
  10. Java语言所有异常类均继承自_要继承自定义异常类的继承方式必须使用 ( ) 关键字_学小易找答案...
  11. 常见iPhone设备尺寸及分辨率(持续更新)
  12. python从外部传入参数_Python学习杂记_8_从程序外部传参的办法sys.argv
  13. python给一列数据增加前缀_为Datafram的特定列添加前缀
  14. 基于Springboot实现英语在线学习系统
  15. word文档中如何将软回车替换为硬回车
  16. 解决Windows PowerShell 乱码
  17. Unity_EasyAR_AR大屏幕开发
  18. 数字温度计设计c语言,数字温度计的设计与制作
  19. nginx php .htaccess,Linux下nginx支持.htaccess文件实现伪静态的方法
  20. (自学)sklearn决策树基础知识|解决centos7.8 graphviz报错不能画图的问题

热门文章

  1. android view强制重绘_android view 相关方法 layout draw 布局 重绘 | 学步园
  2. tcp连接多久会自动断开_苹果M1 Mac用户报告蓝牙连接问题:外设经常会断开
  3. ios模拟器装ipa包_在iOS开发的时候如何在模拟器中安装APP
  4. C语言结构体通过 scanf初始化
  5. python 在Windows 下切换工作目录
  6. 149. Leetcode 1005. K 次取反后最大化的数组和 (贪心算法-基础题目)
  7. MAS 714总复习
  8. CMA-ES 算法初探
  9. 【新功能,新插件】-全新来袭,CSDN浏览器助手这一款无广告干净界面插件你值得拥有!
  10. 机器学习算法源码全解析(一)-带你深入理解随机森林(RandomForest)原理及如何防止 Dropout