手把手教你用Python进行回归(附代码、学习资料)

2023-10-26

作者: GURCHETAN SINGH 

翻译:张逸

校对:丁楠雅

本文共5800字,建议阅读8分钟。
本文从线性回归、多项式回归出发,带你用Python实现样条回归。


我刚开始学习数据科学时,第一个接触到的算法就是线性回归。在把这个方法算法应用在到各种各样的数据集的过程中,我总结出了一些它的优点和不足。


首先,线性回归假设自变量和因变量之间存在线性关系,但实际情况却很少是这样。为了改进这个问题模型,我尝试了多项式回归,效果确实好一些(大多数情况下都是如此会改善)。但又有一个新问题:当数据集的变量太多的时候,用多项式回归很容易产生过拟合。



由于而且我建立的模型总是过于灵活,它可能在测试集上结果很好,但在那些“看不见的”数据上表现的就差强人意了。后来我看到另外一种称为样条回归的非线性方法---它将线性/多项式函数进行组合,用最终的结果来拟合数据。


在这篇文章中,我将会介绍线性回归、多项式回归的基本概念,然后详细说明关于样条回归的更多细节以及它的Python实现。


注:为了更好的理解本文中所提到的各种概念,你需要有线性回归和多项式回归的基础知识储备。这里有一些相关资料可以参考:


https://www.analyticsvidhya.com/blog/2015/08/comprehensive-guide-regression/


本文结构


  • 了解数据

  • 简单回顾线性回归

  • 多项式回归:对线性会回归的改进

  • 理解样条回归及其实现

    • 分段阶梯函数

    • 基函数

    • 分段多项式

    • 约束和样条

    • 三次样条和自然三次样条

    • 确定节点的数量和位置

    • 比较样条回归和多项式回归


了解数据


为了更好的理解这些概念,我们选择了工资预测数据集来做辅助说明。你可以在这儿下载:


https://drive.google.com/file/d/1QIHCTvHQIBpilzbNxGmbdEBEbmEkMd_K/view


这个数据集是从一本最近热门的书《Introduction to Statistical learning》(http://www-bcf.usc.edu/~gareth/ISL/ ISLR%20Seventh%20Printing.pdf)上摘取下来的。


我们的数据集包括了诸如ID、出生年份、性别、婚姻状况、种族、教育程度、职业、健康状况、健康保险和工资记录这些信息。为了详细解释样条回归,我们将只用年龄作为自变量来预测工资(因变量)。


让我们开始吧:


#导入需要的包

import pandas as pd

import numpy as np

import statsmodels.api as sm

import matplotlib.pyplot as plt

%matplotlib inline

#读入数据

data = pd.read_csv("Wage.csv")

data.head()


我们会得到这样的结果:



继续:


data_x = data['age']

data_y = data['wage']

#将数据划分为训练集和验证集

from sklearn.model_selection import train_test_split

train_x, valid_x, train_y, valid_y = train_test_split(data_x, data_y, test_size=0.33, random_state = 1)

#对年龄和工资的关系进行可视化

import matplotlib.pyplot as plt

plt.scatter(train_x, train_y, facecolor='None', edgecolor='k', alpha=0.3)plt.show()


我们会得到这样的图:



看到上边这个散点图,你会想到什么?这到底是代表正相关还是负相关?或者说根本没有联系?大家可以在下方的评论区说说自己的观点。


介绍线性回归


线性回归是预测模型中最简单同时应用最广泛的统计方法。它是用来解决基于回归任务的一种监督学习方法。


这种方法建立了自变量和因变量之间线性的关系,所以被称为线性回归。主要是一个线性方程,就像下边这个式子。可以这么理解:我们的特征就是一组带系数的自变量。



这个式子中,我们认为Y是因变量,X为自变量,所有的β都是系数。这些系数即为对应特征的权重,表示了每个特征的重要性。比如说:某个预测的结果高度依赖于诸多特征中的一个(X1),则意味着与其他所有特征相比,X1的系数(即权重)值会更高。


下面我们来试着理解一下只有一个特征的线性回归。即:只有一个自变量。它被称为简单线性回归。对应的式子是这样的:



前面提到,我们只用年龄这一个特征来预测工资,所以很显然,可以在训练集上应用简单线性回归,并且在验证集上计算该模型的误差(RMSE)


from sklearn.linear_model import LinearRegression

#拟合线性回归模型

x = train_x.reshape(-1,1)

model = LinearRegression()

model.fit(x,train_y)

print(model.coef_)

print(model.intercept_)

-> array([0.72190831])

-> 80.65287740759283

#在验证集上进行预测

valid_x = valid_x.reshape(-1,1)

pred = model.predict(valid_x)


#可视化

#我们将使用valid_x的最小值和最大值之间的70个点进行绘制

xp = np.linspace(valid_x.min(),valid_x.max(),70)

xp = xp.reshape(-1,1)

pred_plot = model.predict(xp)


plt.scatter(valid_x, valid_y, facecolor='None', edgecolor='k', alpha=0.3)

plt.plot(xp, pred_plot)

plt.show()


得出图像如下:



现在对预测出的结果算一下RMSE:


from sklearn.metrics import mean_squared_error

from math import sqrt

rms = sqrt(mean_squared_error(valid_y, pred))

print(rms)

-> 40.436


从上边的图中我们可以看出,线性回归模型并没有抓住数据的全部特点,对于工资预测问题来说,这个方法表现的并不理想。


所以结论是,尽管线性模型在描述和实现上比较简单,并且非常容易理解并应用。但它在预测能力方面还是比较有限。这是因为线性模型假定自变量和因变量之间总是存在线性关系。这个假设是很弱的,它仅仅是近似,而且在有些情况下,近似效果非常差。


在下面要提到的其他方法中,得把这种线性的假设暂且搁到一边,但也不能完全抛之脑后。我们会在这个最简单的线性模型基础上进行拓展,得到多项式回归、阶梯函数,或者更复杂一点的,比如样条回归,也会在下面进行介绍。


线性回归的改进:多项式回归


来看看这样一组可视化的图:



这些图看起来挖掘出了年龄和工资之间的更多联系。它们是非线性的,因为在建立年龄和工资模型的时候使用的是非线性等式。这种使用非线性函数的回归方法,叫做多项式回归。


多项式回归通过增加额外的预测项对简单线性模型进行了拓展。具体来讲,是将每个原始预测项提升了幂次。例如,一个三次回归使用了这样三个变量:作为预测项。它提供了一个简单的办法来让非线性更好的拟合数据。


那这种方法是如何做到用非线性模型来代替线性模型,在自变量和因变量之间建立关系的呢?这种改进的根本,是使用了一个多项式方程取代了原来的线性关系。



但当我们增加幂次的值时,曲线开始高频震荡。这导致曲线的形状过于复杂,最终引起过拟合现象。


#为回归函数生成权重,设degree=2

weights = np.polyfit(train_x, train_y, 2)

print(weights)

-> array([ -0.05194765,   5.22868974, -10.03406116])

#根据给定的权重生成模型

model = np.poly1d(weights)

#在验证集上进行预测

pred = model(valid_x)

#我们只画出其中的70个点

xp = np.linspace(valid_x.min(),valid_x.max(),70)

pred_plot = model(xp)

plt.scatter(valid_x, valid_y, facecolor='None', edgecolor='k', alpha=0.3)

plt.plot(xp, pred_plot)

plt.show()



类似的,我们画出不同degree值对应的图:



不幸的是,多项式回归也有很多问题,随着等式的复杂性的增加,特征的数量也会增长到很难控制的地步。而且,即便是在上述这个简单的一维数据集上,多项式回归也可能会导致过拟合。


除此之外,还有其他问题。比如:多项式回归本质是非局部性的。也就是说,在训练集中改变其中一个点的y值,会影响到离这个点很远的其他数据的拟合效果。因此,为了避免在整个数据集上使用过高阶的多项式,我们可以用很多不同的低阶多项式函数来作为替代。


样条回归法及其实现


为了克服多项式回归的缺点,我们可以用另外一种改进的回归方法。这种方法没有将模型应用到整个数据集中,而是将数据集划分到多个区间,为每个区间中的数据单独拟合一个模型。这种方法被称为样条回归。


样条回归是最重要的非线性回归方法之一。在多项式回归中,我们通过在已有的特征上应用不同的多项式函数来产生新的特征,这种特征对数据集的影响是全局的。为了解决这个问题,我们可以根据数据的分布特点将其分成不同的部分,并在每一部分上拟合线性或低阶多项式函数。



进行分区的点被称为节点。我们可以用分段函数来对每个区间中的数据进行建模。有很多不同的分段函数可以用来拟合这些数据。


在下一小节中,我们会详细介绍这些函数。


  • 分段阶梯函数


阶梯函数是一种最常见的分段函数。它的函数值在一段时间个区间内会保持一个常数不变。我们可以对不同的数据区间应用不同的阶梯函数,以免对整个数据集的结构产生影响。


在这里我们将X的值进行分段处理,并且对每一部分拟合一个不同的常数。


更具体来讲,我们设置分割点C1,C2,...Ck。在X的范围内构造K+1个新变量。



上图中的I()是一个指示函数,如果条件满足,则返回1,反之则返回0.比如当Ck≤X时,函数值I(Ck≤X)为1,反之它就等于0.。对于任意给定的值X,C1,C2,...Ck只能有一个值为非零。因为X只能被分到一个区间中。


#将数据划到四个区间中

df_cut, bins = pd.cut(train_x, 4, retbins=True, right=True)

df_cut.value_counts(sort=False)


->(17.938, 33.5]    504

(33.5, 49.0]      941

(49.0, 64.5]      511

(64.5, 80.0]       54

Name: age, dtype: int64

df_steps = pd.concat([train_x, df_cut, train_y],

keys=['age','age_cuts','wage'], axis=1)

#将讲年龄编码为哑变量

df_steps_dummies = pd.get_dummies(df_cut)

df_steps_dummies.head()



df_steps_dummies.columns = ['17.938-33.5','33.5-49','49-64.5','64.5-80']

#拟合广义线性模型

fit3 = sm.GLM(df_steps.wage, df_steps_dummies).fit()


#同样将验证集划分到四个桶中

bin_mapping = np.digitize(valid_x, bins)

X_valid = pd.get_dummies(bin_mapping)


#去掉离群点

X_valid = pd.get_dummies(bin_mapping).drop([5], axis=1)


#进行预测

pred2 = fit3.predict(X_valid)


#计算RMSE

from sklearn.metrics import mean_squared_error

from math import sqrt

rms = sqrt(mean_squared_error(valid_y, pred2))

print(rms)

->39.9


#在这我们只画出70个观察点的图

xp = np.linspace(valid_x.min(),valid_x.max()-1,70)

bin_mapping = np.digitize(xp, bins)

X_valid_2 = pd.get_dummies(bin_mapping)

pred2 = fit3.predict(X_valid_2)

#进行可视化

fig, (ax1) = plt.subplots(1,1, figsize=(12,5))

fig.suptitle('Piecewise Constant', fontsize=14)


#画出样条回归的散点图

ax1.scatter(train_x, train_y, facecolor='None', edgecolor='k', alpha=0.3)

ax1.plot(xp, pred2, c='b')

ax1.set_xlabel('age')

ax1.set_ylabel('wage')

plt.show()



但是这种分段的方法有明显的概念性问题。最明显的问题是,我们研究的大多数问题会随着输入的改变有一个连续变化的趋势。但这种方法不能构建预测变量的连续函数,因此大多数情况下,应用这种方法,首先得假定输入和输出之间没有什么关系。


例如在上面的图表中,我们可以看到,拟合第一个区间的函数显然没有捕捉到工资随年龄的增长而增长的趋势。


  • 基函数


为了捕捉回归模型中的非线性,我们得变换部分或者全部的预测项。而为了避免将每个自变量视为线性的,我们希望有一个更普遍的“变换族”来应用到预测项中。它应该有足够的灵活性,以拟合各种各样形状的曲线(当模型合适时),同时注意但不能过拟合。


这种可以组合在一起捕捉一般数据分布的变换被称为基函数。在这个例子中,基函数是b1(x),b2(x),...,bk(x)


此时,我们拟合的不再是一个线性模型,而是如下所示:



下面我们来看一个普遍使用的基函数:分段多项式。


  • 分段多项式


首先,分段多项式在X的不同范围内拟合的是不同的低阶多项式,而不是像分段阶梯函数那样拟合常数。由于我们使用的多项式次数较低,因此不会观察到曲线有什么大的震荡。


比如:分段二次多项式通过拟合二次回归方程来起作用:



上式中的系数β0、β1还有β2在X的不同区间内是取值不一样的。


一个分段三次多项式,在点C处存在节点,那么它会具有以下形式:



换句话说,我们在数据上拟合了两个不同的三次多项式:一个应用于满足Xi<C的数据,另一个应用于Xi>C的那部分。


第一个多项式函数的系数为: β01, β11, β21, β31,第二个系数则是 β02, β12, β22, β32。这两个多项式函数中的每一个都可以用最小均方误差来拟合。


注意:这个多项式函数有8个自由度,每个多项式有4个(因为是4个变量)。


使用的节点越多,得到的分段多项式就更加灵活,因为我们对X的每一个区间都使用不同的函数,并且这些函数仅仅与该区间中数据的分布情况相关。一般来说,如果我们在X的范围内设置K个不同的节点,最终会拟合K+1个不同的三次多项式。 而且我们其实可以使用任何低阶的多项式来拟合某一段的数据。比如:可以改用分段线性函数,实际上,上面使用的阶梯函数是0阶的分段多项式。


下面我们来看看构建分段多项式时应遵循的一些必要条件和约束。


  • 约束和样条


在使用分段多项式时,我们得非常小心,因为它有很多的限制条件。看看下边这幅图:



我们可能会遇到这种情况----节点两端的多项式在节点上不连续。这是要避免的,因为多项式应该为每一个输入生成一个唯一的输出。


上面那幅图很显然:在第一个节点处有两个不同的值。所以,为了避免这种情况,要有一个限制条件:节点两端的多项式在节点上也必须是连续的。



增加这个限制条件之后,我们得到了一组连续的多项式。但这样就够了吗?答案显然是否定的。在继续阅读下文之前,读者可以先考虑一下这个问题,看看我们是不是漏掉了什么。


观察上面的图可以发现,在节点处,曲线还是不平滑。为了得到在节点处依然光滑的曲线,我们又加了一个限制条件:两个多项式的一阶导数必须相同。要注意的一点是:我们每在分段三次多项式上增加一个约束,都相当于降了一个自由度。因为我们降低了分段多项式拟合的复杂性。因此,在上述问题中,我们只使用了10个自由度而不是12个。



在加上关于一阶导数的约束以后,我们得到了如上所示的图形。因为刚才新增加约束的缘故,它的自由度从12个减少到了8个。但即便目前曲线看起来好多了,但还有一些可以改进的空间。现在,我们又要新增加一个约束条件:两个多项式在节点处的二次导数必须相等。



这次的结果看起来真的是好多了。它进一步将自由度下降为6个。像这样具有m-1阶连续导数的m阶多项式被称为样条。所以,在上边的图中,我们实际上是建立了一个三次样条。


  • 三次样条和自然三次样条


三次样条是具有一组额外约束(连续性、一阶导数连续性、二阶导数连续性)的分段多项式。通常,一个有K个节点的三次样条其自由度是4+K。很少会用到比三次还要高阶的样条(除非是对光滑性非常感兴趣)


from patsy import dmatrix

import statsmodels.api as sm

import statsmodels.formula.api as smf

#生成一个三节点的三次样条(25,40,60)

transformed_x = dmatrix("bs(train, knots=(25,40,60), degree=3, include_intercept=False)", {"train": train_x},return_type='dataframe')


#在数据集及上拟合广义线性模型

fit1 = sm.GLM(train_y, transformed_x).fit()


#生成一个4节点的三次样条曲线

transformed_x2 = dmatrix("bs(train, knots=(25,40,50,65),degree =3, include_intercept=False)", {"train": train_x}, return_type='dataframe')


#在数据集上拟合广义线性模型

fit2 = sm.GLM(train_y, transformed_x2).fit()


#在两个样条上均进行预测

pred1 = fit1.predict(dmatrix("bs(valid, knots=(25,40,60), include_intercept=False)", {"valid": valid_x}, return_type='dataframe'))

pred2 = fit2.predict(dmatrix("bs(valid, knots=(25,40,50,65),degree =3, include_intercept=False)", {"valid": valid_x}, return_type='dataframe'))


#计算RMSE值

valuesrms1 = sqrt(mean_squared_error(valid_y, pred1))

print(rms1)

-> 39.4

rms2 = sqrt(mean_squared_error(valid_y, pred2))

print(rms2)

-> 39.3

#我们将使用70个点进行图形的绘制

xp = np.linspace(valid_x.min(),valid_x.max(),70)

#进行一些预测

pred1 = fit1.predict(dmatrix("bs(xp, knots=(25,40,60), include_intercept=False)", {"xp": xp}, return_type='dataframe'))

pred2 = fit2.predict(dmatrix("bs(xp, knots=(25,40,50,65),degree =3, include_intercept=False)", {"xp": xp}, return_type='dataframe'))

#画出样条曲线和误差图

plt.scatter(data.age, data.wage, facecolor='None', edgecolor='k', alpha=0.1)

plt.plot(xp, pred1, label='Specifying degree =3 with 3 knots')

plt.plot(xp, pred2, color='r', label='Specifying degree =3 with 4 knots')

plt.legend()

plt.xlim(15,85)

plt.ylim(0,350)

plt.xlabel('age')

plt.ylabel('wage')

plt.show()



众所周知,多项式拟合数据在边界附近往往表现的很不稳定。这是很危险的。样条也有类似的问题。那些拟合超出边界节点数据的多项式比该区域区间中相应的全局多项式得出的结果更加让人意外。为了将这种曲线的平滑性延伸到边界之外的节点上,我们将使用被称为自然样条的特殊类型样条。


自然三次样条又多一个约束条件,即:要求函数在边界之外是线性的。这个条件将三次和二次部分变为0,每次自由度减少2个,两个端点共减少4个自由度,最后k+4减少为k。


#生成自然三次样条

transformed_x3 = dmatrix("cr(train,df = 3)", {"train": train_x}, return_type='dataframe')

fit3 = sm.GLM(train_y, transformed_x3).fit()


#在验证集上进行预测

pred3 = fit3.predict(dmatrix("cr(valid, df=3)", {"valid": valid_x}, return_type='dataframe'))

#计算RMSE的值

rms = sqrt(mean_squared_error(valid_y, pred3))

print(rms)

-> 39.44


#选取其中70个点进行作图

xp = np.linspace(valid_x.min(),valid_x.max(),70)

pred3 = fit3.predict(dmatrix("cr(xp, df=3)", {"xp": xp}, return_type='dataframe'))

#画出样条曲线

plt.scatter(data.age, data.wage, facecolor='None', edgecolor='k', alpha=0.1)

plt.plot(xp, pred3,color='g', label='Natural spline')

plt.legend()

plt.xlim(15,85)

plt.ylim(0,350)

plt.xlabel('age')

plt.ylabel('wage')

plt.show()



  • 如何选取确定节点的数量和位置


当我们拟合一个样条曲线时,该如何选取节点呢?一个可行的方法是选择那些剧烈变化的区域,因为在这种地方,多项式的系数会迅速改变。所以,可以将在那些我们认为函数值变化剧烈的地方设置更多的节点,在比较稳定的地方少放一些。


不过虽然这种方法虽然效果还可以,但是实际上经常是以一种统一的方式来选取节点。一种方法是指定所需的自由度,然后由软件自动的将相应数量的节点放在数据的统一分位数处。


或者另一种选择是改变节点的数量,不断实践来测试到底哪一种方案会得到更好的曲线。


当然还有一种更加客观的做法-----交叉验证,要是用这种方法,我们要做到以下几点:


  • 取走一部分数据

  • 选择一定数量的节点使样条能拟合剩下的这些数据

  • 再用样条去预测之前取走的那部分数据


不断重复这个过程,直到所有的数据都被取走一次。再计算整个交叉验证的RMSE。这个过程可以针对不同数量的节点进行重复,最后我们选择使得RMSE值最小的那个K值。


  • 比较对样条回归和多项式回归进行比较


通常情况下,样条回归总是表现得的总是比多项式回归要好一些。这是因为多项式回归必须要用很高阶的项才能对数据拟合出比较灵活的模型。但是样条回归则是通过增加节点的数量做到这一点,同时还保持了阶数不变。


而且样条回归方法会得到更加稳定的模型。它允许我们在函数变化比较剧烈的地方增加更多节点,反之,函数变化平缓的地方节点就会少一些。多项式模型如果要求更灵活,它就会牺牲边界上的稳定性,但三次自然样条却很好的兼顾了灵活性和稳定性。



结语


在这篇文章中,我们学习了样条回归以及其在与线性回归及多项式回归相比时的一些优势。还有另外一种生成样条的方法叫做平滑样条。它与Ridge/Lasso正则化类似,乘惩罚结合了损失函数和平滑函数。大家可以在《统计学习入门》一书中阅读更多的内容。或者你感兴趣的话,也可以在一个具有很多变量的数据集上试试看这些方法,亲身体会一下个中差异。


译者补充


本文所有实验需要的包汇总:



原文标题:Introduction to Regression Splines (with Python codes)

原文链接:https://www.analyticsvidhya.com /blog/2018/03/introduction-regression-splines-python-codes/


译者简介


张逸,中国传媒大学大三在读,主修数字媒体技术。对数据科学充满好奇,感慨于它创造出来的新世界。目前正在摸索和学习中,希望自己勇敢又热烈,学最有意思的知识,交最志同道合的朋友。

翻译组招募信息

工作内容:需要一颗细致的心,将选取好的外文文章翻译成流畅的中文。如果你是数据科学/统计学/计算机类的留学生,或在海外从事相关工作,或对自己外语水平有信心的朋友欢迎加入翻译小组。

你能得到:定期的翻译培训提高志愿者的翻译水平,提高对于数据科学前沿的认知,海外的朋友可以和国内技术应用发展保持联系,THU数据派产学研的背景为志愿者带来好的发展机遇。

其他福利:来自于名企的数据科学工作者,北大清华以及海外等名校学生他们都将成为你在翻译小组的伙伴。


点击文末“阅读原文”加入数据派团队~

转载须知

如需转载,请在开篇显著位置注明作者和出处(转自:数据派ID:datapi),并在文章结尾放置数据派醒目二维码。有原创标识文章,请发送【文章名称-待授权公众号名称及ID】至联系邮箱,申请白名单授权并按要求编辑。

发布后请将链接反馈至联系邮箱(见下方)。未经许可的转载以及改编者,我们将依法追究其法律责任。

点击“阅读原文”拥抱组织

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手把手教你用Python进行回归(附代码、学习资料) 的相关文章

  • spark基本知识点之内存管理

    原地址 点击打开链接 Spark Memory Management 25 Replies Starting Apache Spark version 1 6 0 memory management model has changed Th
  • GIS项目启动时手动添加依赖

    gis项目在idea下启动前需要手动安装的包 mvn install install file DgroupId org geotools jdbc DartifactId gt jdbc oracle Dversion 18 2 Dpac
  • centOs 6.5 ssh配置无密码登入

    1 安装ssh 若没安装的话 sudo apt get install ssh 2 配置为可以免密码登陆本机 2 1查看在master用户下是否存在 ssh文件夹 ssh前面有 的是隐藏文件夹 输入命令ls a home master 我的
  • omnifocus3透视 任务分类实例详解

    目录 1任务分类 2标签 任务细化的一种属性 3任务分类实例详解 4透视 上大学之前 好巧 今天9号 高考结束 我们每周的任务数量很明确 本学期几本书的学习 复习 但是步入社会之后 参与项目数量逐渐增加 需要沟通的人也越来越复杂 每日任务不
  • 认识 ESP-IDF-v4.3+工程结构(ESP32-C3应用调整示例)

    ESP32 C3 学习测试到今天 一直在使用 ESP IDF 的框架 但是还从来没有注意过工程结构 遇到复杂一点的项目 工程结构就显得太乱了 本文就来了解下 ESP IDF 工程结构 目录 前言 一 ESP IDF工程基本框架 1 1 工程
  • 数学是成就卓越开发人员的必备技能

    本文转载至 http blog jobbole com 444 编者按 原文作者Alan Skorkin是一名软件开发人员 他在博客中分享对软件开发相关的心得 其中有很多优秀的文章 本文就是其中一篇 作者认为 成为优秀的开发人员 可以没有数
  • javaEE企业级框架ssm知识点整合【思维导图】

    ssm Spring SpringMVC Mybatis 框架是轻量级javaEE应用开发最受欢迎的一种组合框架之一 使用这种框架的项目使JavaEE架构具有高度可维护性和可扩展性 同时极大地提高了项目的开发效率 降低了开发和维护的成本 而
  • webkit和webkit2的区别

    转自 http blog csdn net shunzi 1984 article details 6196483 原文地址 https trac webkit org wiki WebKit2 webkit2为了在API层支持多进程改变了
  • Linux “/“ 分区扩容

    前言 扩容是一项很简单的工作 但是有时候因为长时间没有操作过扩容 指令会比较生疏 因此写一篇扩容的文档 方便在再次失忆的情况下能快速回忆起操作流程 逻辑卷扩容的流程 创建PV gt 扩容VG gt 扩容LV 以下是扩容的详细流程 1 查看当
  • 人工智能梯度下降的优化器SGD、Momentum、AdaGrad、Adam的数学原理以及无框架实现

    系列文章目录 人工智能 梯度下降的原理和手写实现 文章目录 系列文章目录 前言 一 梯度下降优化器是什么 二 SGD优化方法 1 SGD是什么 2 SGD的数学原理 3 SGD的实现 4 SGD的缺陷 三 Momentum优化方法 1 Mo
  • 为什么公司规定所有接口都必须加上分布式锁,你知道吗?

    上一篇文章我们聊了聊Redisson这个开源框架对Redis分布式锁的实现原理 如果有不了解的兄弟可以看一下 都2022年了 出去面试连分布式锁的源码你都不会画 今天就给大家聊一个有意思的话题 每秒上千订单场景下 如何对分布式锁的并发能力进
  • 如何通过代码获取framedebugger里面的drawcall信息

    最近想做个性能工具 用来分析当前drawcall里面的具体调用 不知道unity有没有获取数据的具体接口 不过framedebugger里面的确有相关数据 这是方案一 另外一个方案是hook 理论上应该参考下renderdoc的实现应该就可
  • 使用scrapy爬取数据

    安装scrapy 使用清华镜像 打开PyCharm 安装scrapy框架 pip install i https pypi tuna tsinghua edu cn simple scrapy 新建一个名为python scrapy的项目
  • 深入浅出图解CNN-卷积神经网络

    首先 介绍一下卷积的来源 它经常用在信号处理中 用于计算信号的延迟累积 假设一个信号发生器每个时刻t产生一个信号xt 其信息的衰减率为wk 即在k 1个时间步长后 信息为原来的wk 倍 假设w1 1 w2 1 2 w3 1 4 时刻t收到的
  • linux查找目录下的所有文件中是否含有某个字符串

    Linux查找文件内容的常用命令方法 从文件内容查找匹配指定字符串的行 grep 被查找的字符串 文件名 例子 在当前目录里第一级文件夹中寻找包含指定字符串的 in文件 grep thermcontact in 从文件内容查找与正则表达式匹
  • [论文阅读]《Database Maanagement Systems》-第六章

    第六章 QUERY BY EXAMPLE QBE 查询示例 QBE P201 P216 Example is always more efficacious than precept 身教胜于言教 榜样总是比教训更有效 precept 规则
  • openGL之API学习(一七三)glsl如何设置版本version和兼容性

    version 120 version 120 core version 120 compatibility version 300 es GLSL ES 提供了一个 version 指令来指定着色器使用的GLSL ES的版本 如果不指定G
  • c++ 日志输出库 spdlog 简介

    spdlog是一个开源的 快速的 仅有头文件的C 11 日志库 它提供了向流 标准输出 文件 系统日志 调试器等目标输出日志的能力 它支持的平台包括Windows Linux Mac Android iOS 官方参考 https githu
  • 后缀自动机(SAM)——黑盒使用方案

    首先讲下后缀自动机吧 会写一下部分必要的原理 其他的原理不做解释 代码未讲解的部分希望能当做黑盒来使用 既不了解具体原理但知道其性质以及如何使用 我实在是佩服发明出AC自动机 回文自动机 后缀自动机这人 前置知识 AC自动机中的Fail树
  • 如何使用Chrome浏览器模拟弱网情况

    点击谷歌浏览器图标 打开浏览器后 按下F12键 弹出开发者工具窗口 刷新网页 页面的加载速度为597ms 在开发者工具中 点击Online 在弹出的菜单中点击Slow 3G 慢速3G网络 重新加载网站 发现页面的加载速度变慢了 变成6 5s

随机推荐

  • openssl engine在tls中的应用

    openssl engine的实现和原理在上一篇文章 https blog csdn net liu942947766 article details 128837041 spm 1001 2014 3001 5502 openssl en
  • MATLAB随机生成m个三维坐标点,且各个坐标点之间的距离不小于n

    randi函数 randi max m n 生成均匀分布的随机整数 max生成的随机整数最大值 生成m行n列的矩阵 编写函数sampling function x y z sampling lowx upx lowy upy lowz up
  • 第五篇:进阶篇 发动机的噪声特性

    本专栏分享传统NVH知识点 从声学理论 材料声学 汽车噪声振动分析 车辆及其零部件甚至原材料的声学测试方法等多维度介绍汽车NVH 一些专用术语同时给出了中英文对照 欢迎新人 同行 爱好者一起交流 由于内容写的较为仓促 有误的地方欢迎大家批评
  • JS优化方法(使用最新的js方法)

    1 带有多个条件的if语句 将多个值放在一个数组中 然后调用数组的includes方法 longhand 直接的 if x abc x def x ghi x jkl logic 逻辑 shorthand 速记 if abc def ghi
  • 【FFmpeg】 音视频解码详细流程

    目录 一 视频解码流程 二 FFMPEG解码流程 三 FFmpeg解码函数 四 FFmpeg解码的数据结构 五 FFmpeg数据结构简介 六 FFmpeg数据结构分析 七 像素数据转换 八 FFMPEG解码 九 FFMPEG解码 视频播放
  • Donation-树形dp-建图

    题目网址 链接 int head maxn int n m cnt tot ll a maxn b maxn c maxn id maxn int fa maxn int lson maxn rson maxn struct node in
  • 用单片机C语言精确延时(定时)的方法

    用单片机C语言精确延时 定时 的方法 作者 51hei 来源 原创 点击数 更新时间 2009年09月29日 字体 大 中 小 最近在忙着单片机的项目 偶尔停下来小结了一下最近的收获 还是有不少可贵的收益的 本人在闲暇的时候对单片机C语言下
  • 显示本地openssl支持的加密算法

    在命令行中输入命令 openssl list ciper algorithms 运行后即刻显示支持的加密算法 END
  • [2022CISCN]初赛 复现

    ez usb 刚开始直接提取usb键盘流量 发现导出有问题 键盘流量 搜索8个字节长度的数据包 这里也能发现版本有2 8 1和2 10 1两种 因此猜测需要分别导出 tshark r ez usb pcapng Y usb data len
  • 16. GD32F103C8T6入门教程-adc 使用教程2-dma+连续扫描方式采集数据

    adc 使用教程2 dma 连续扫描方式采集数据 adc 的扫描模式就是把配置了规则或注入通道按照配置的顺序采集一轮 adc 的连续转换模式就是把配置了规则或注入通道按照配置的顺序采集N轮 注意 dma使用时存在一个外设映射到一个dam外设
  • css动画改变高度有过渡效果,css3-形变、过渡、动画

    一 2D形变 平移 transform translate x y 相对当前位置 向左移动x像素 像下移动y像素 transform translateX num 相对当前位置 向左移动num像素 transform translateY
  • OpenGLES从2.0到3.0的变化

    1 在着色器文件中添加 version 300 es 表明使用3 0版本 如果不添加则使用默认2 0版本 注意使用opengles3 0的API的时候必须添加 version 300 es 2 GLES 3 0中将GLES 2 0的 att
  • 两个栈来实现一个队列的C++代码

    利用两个栈来实现一个队列 这个问题很常见 最关键的是要有好的思路 至于实现 那是很简单的事情了 在本文中 也想说说自己的思路 但是 我觉得用代码来表述思路更符合我的习惯 也是我的菜 所以 仅仅给出代码 如有需要 大家可以根据代码来理解思路
  • Oracle 11g R2静默安装

    2015年1月6日 测试安装Oracle 11g R2静默安装安装 环境是vmware平台虚拟机 做个记录 CentOS 6 5 x64安装Oracle 11g R2 一 下载地址 http www oracle com technetwo
  • Java实现将数字转换成中文大写

    程序功能 支持将仟亿数字转换成中文数字表示 如 110 12 转换成壹佰壹拾元壹角贰分 算法思路 将数字 分成整数部分和小数部分 小数部分四舍五入到两位 分别进行转换 然后将转换后的结果合并后 生成最终结果 转换过程关键怎么处理中间的零 以
  • 索引2

    索引和全文索引 索引的目的是提高性能 索引提供了一种基于一列或多列的值对表的数据行进行快速访问的方法 索引提供的是表为数据 的逻辑顺序 规划合理的索引能够减少访问所需的时间 从而大大提高数据库的性能 索引 索引为性能带来的好处却是有代价的
  • R手册(Parallel Computing)--foreach

    R手册 Parallel Computing foreach foreach foreach 后端支持 library doParallel 为foreah包提供一个并行的后端 n cores lt detectCores logical
  • 树莓派4B与Android之缘——Android应用MiniChat聊天软件

    基本介绍和总体架构 一 应用介绍 一 基本介绍 MiniChat是一款聊天软件 你可以通过此软件进行聊天 本应用集成了融云模块 从而实现集成通讯 主要功能是账号注册 登录 好友添加 好友间发送文字 文件信息 二 应用展示 1 登录界面 未输
  • Java 终止嵌套for 循环总结

    public class NestedLoopDemo public static void main String args 第一步 构建嵌套for 循环 for int i 0 i lt 10 i for int j 0 j lt 10
  • 手把手教你用Python进行回归(附代码、学习资料)

    作者 GURCHETAN SINGH 翻译 张逸 校对 丁楠雅 本文共5800字 建议阅读8分钟 本文从线性回归 多项式回归出发 带你用Python实现样条回归 我刚开始学习数据科学时 第一个接触到的算法就是线性回归 在把这个方法算法应用在