《Machine Learning in Action》—— 浅谈线性回归的那些事

手撕机器学习算法系列文章已经肝了不少,自我感觉质量都挺不错的。目前已经更新了支持向量机SVM、决策树、K-近邻(KNN)、贝叶斯分类,读者可根据以下内容自行“充电”(持续更新中):

阅读过上述那些文章的读者应该都知道,上述内容都属于分类算法,分类的目标变量都是标称型数据(关于标称型和数据型数据的意思的可参考上文)。而本文主要讲述的内容是线性回归,它是一种回归拟合问题,会对连续性数据做出预测,而非判别某个样本属于哪一类。

本文主要包括的内容有如下几部分:

  • 线性回归,我们来谈谈小姐姐如何相亲
  • 揭开梯度下降算法的神秘面纱
  • 基于梯度下降算法实现线性回归拟合

一、线性回归,我们来谈谈小姐姐如何相亲

回归预测,回归预测,说到底就包括两个部分。

一个是回归(拟合),另一个是预测。回归是为预测做准备或者说是铺垫,只有基于已有的数据集我们才能构建一个的回归模型,然后根据这个回归模型来处理新样本数据的过程就是预测。

而线性回归就是我们的回归模型属于线性的,也就是说我们样本的每个属性特征都最多是一次的(进来的读者 应该都知道吧)

为了让读者对线性回归有个基本的了解,我们来聊聊小姐姐的相亲故事。

故事是这样的。

在很久很久以前,有位小姐姐打算去相亲,她比较在意对象的薪资情况,但这种事情也不太好意思直入主题,你说是吧?所以呢,她就想着通过相亲对象本身的属性特征来达到一个预测薪资的目的。假如说这位小姐姐认为对象的薪资主要有两个部分的数据的组成,分别是对象的年龄和头发量。对此,小姐姐想要构建出这么一个关于薪资的线性模型:

\[salary = w_1 * hair\_number + w_2 * age
\]

中文形式的描述就是:

\[小姐姐对象的薪资 = w_1 * 小姐姐对象的发量 + w_2 * 小姐姐对象的年龄
\]

所以呢,小姐姐现在的目的就是想要得到这么一个\(w_1和w_2\)的值,然后观察和询问相亲对象的发量以及年龄,就可以根据这个线性模型计算得出其相亲对象的薪资情况。

那么,如何得到\(w_1,w_2\)的值呢???就在小姐姐脑阔疼的厉害之时,Taoye是这么手握手教小姐姐的:“小姐姐,你可以先相亲1000个对象,观察并询问对象的发量和年龄之后,然后通过社会工程学来得到他的薪资情况。有了这1000组对象数据之后,你就能训练出\(w_1和w_2\)的值,从而得到误差达到最小时候的这个线性模型”

小姐姐听完Taoye的讲述之后,真的是一语惊醒梦中人啊,心想:妙啊,就这么干!!!

以上例子中的内容纯属Taoye胡扯,只为描述线性回归的过程,不代表任何观点。

二、揭开梯度下降算法的神秘面纱

通过上述小姐姐的相亲故事,相信各位看官都已经对线性回归的过程有了一个基本的认识,而要具体操作线性回归,我们还需明白一个在机器学习领域中比较重要的算法,也就是梯度下降算法。

要理解梯度下降算法,我们可以将其类比成一个人下山的过程,这也是我们理解梯度下降算法时候最常用的一个例子,也就是这么一个场景:

有个人被困在山上,他现在要做的就是下山,也就是到达山的最低点。但是呢,现在整座山烟雾缭绕,可见度非常的低,所以下山的路径暂时无法确定,他必须通过自己此刻所在地的一些信息来一步步找到下山的路径。此时,就是梯度下降算法大显身手的时候了。具体怎么做呢?

是这样的,首先会以他当前所在地为基准,寻找此刻所处位置的最陡峭的地方,然后朝着下降的方向按照自己的设定走一步。走一步之后,就来到了一个新的位置,然后将这个新的位置作为基准,再找到最陡峭的地方,沿着这个方向再走一步,如此循环往复,知道走到最低点。这就是梯度下降算法的类别过程,上山同理也是一样,只不过变成了梯度上升算法。

梯度下降算法的基本过程就类似于上述下山的场景。

首先,我们会有一个可微分的函数。这个函数就类似于上述的一座山。我们的目标就是找到这个函数的最小值,也就是上述中山的最低点。根据之前的场景假设,最快的下山的方式就是找到当前位置最陡峭的方向,然后沿着此方向向下走,在这个可微分函数中,梯度反方向就代表这此山最陡峭的方向,也就是函数下降最快的方向。因为梯度的方向就是函数变化最快的方向(在后面会详细解释)

所以,我们重复利用这个方法,在达到一个新的位置之后,反复求取梯度,最后就能到达局部的最小值,这就类似于我们下山的过程。而求取梯度就确定了最陡峭的方向,也就是场景中测量方向的手段。那么为什么梯度的方向就是最陡峭的方向呢?接下来,我们从微分开始讲起:

  • 单变量
\[\begin{aligned}
& \frac{d(x^2+2x+1)}{dx}=2x+2 \\
& \frac{d(2x+1)^2}{dx}=8x+4
\end{aligned}
\]

对于单变量微分来讲,由于函数只有一个变量,所以此时的梯度就是函数的微分,所代表的意义就是在该点所对应的斜率。

  • 多变量(以三个变量为例)
\[\begin{aligned}
& J(x) = 3x_1-2.7x_2+5.1x_3 + 7.9 \\
& \bigtriangledown J(x)=(\frac{dJ}{dx_1},\frac{dJ}{dx_2},\frac{dJ}{dx_3})=(3, -2.7, 5.1)
\end{aligned}
\]

对于多变量函数来讲,此时的梯度就不再是一个具体的值,而是一个向量。我们都知道,向量是有方向的,而该梯度的方向就代表着函数在指定点中上升最快的方向。

这也就说明了为什么我们需要千方百计的求取梯度!我们需要到达山底,就需要在每一步观测到此时最陡峭的地方,梯度就恰巧告诉了我们这个方向。梯度的方向是函数在给定点上升最快的方向,那么梯度的反方向就是函数在给定点下降最快的方向,这正是我们所需要的。所以我们只要沿着梯度的方向一直走,就能走到局部的最低点!

现在,我们不妨通过代码来模拟实现这个过程。假如说,我们现在的目标函数是:

\[y = x^2+2x+1
\]

则其对对应的梯度为:

\[\frac{dy}{dx}=2x+2
\]

对此,我们可以通过如下代码来模拟梯度下降的过程,以寻找出到达最低点时候的\(x\)值:

通过上述代码,我们可以发现,当函数值达到最低点的时候,此时我们的\(x=-0.9999517797740893\),与我们手动计算的\(x=-1\)基本可以划等号,这就是梯度下降所解决的问题。

针对上述代码,这里我们主要说两个点:

①:x_new = x_old - learning_rate * gradient(x_old)

在前进过程中更新x_new的时候,是通过x_old来进行的,之所以在梯度前加一个负号,主要是为了朝着梯度相反的方向前进。在前文我们也要提到,梯度的反方向就是函数在此点下降最快的方向。那么如果是上坡,也就是梯度上升算法,此时x_new的更新过程也就不需要加上负号了。

至于什么时候是梯度上升,什么时候是梯度下降,这个是根据我们实际情况是求最小值,还是最大值来决定的。

②:learning_rate

learning_rate在梯度下降算法中被称作为学习率或者说是步长,意味着我们可以通过learning_rate来控制每一步走的距离,其实就是不要走太快,从而错过了最低点。同时也要保证不要走的太慢,导致我们打到最低点需要花费大量的时间,也就是效率太低了,需要迭代很多次才能满足我们的需求。所以learning_rate的选择在梯度下降法中往往是很重要的!

需要合理的选择learning_rate值,一般来讲可取0.01,具体问题还需具体分析。

总而言之,梯度下降算法主要是根据函数的梯度来对x的值进行不断的更新迭代,以求得函数到达最小值时候的x值。

当然了,以上是该算法的一般形式,同时各位研究者也是提出了一些梯度下降算法的变种形式,主要有以下三种

  1. 随机梯度下降算法(SGD,根据时间复杂度)
  2. 批量梯度下降算法(BGD,根据数据量的大小)
  3. 小批量梯度下降算法(MBGD,算法准确性)

关于上述三种梯度下降算法的变种形式,我们在这里挖个坑,后面有机会再来慢慢把这个坑个填上。

三、基于梯度下降算法实现线性回归拟合

这里代码实战的话,其实是牵涉到对神经网络的理解,不过我们在这里不着重讲解神经网络的内容,只简单的提一下,待手撕机器学习系列文章完成之后再来详细看看。

参考资料:《TensorFlow深度学习》——龙龙老师

我们都知道,人的大脑中包含了大量的神经元细胞,每个神经元都通过树突来获取输入的信号,然后通过轴突传递并输出信号,而神经元与神经元之间相互连接从而构成了巨大的神经网络。生物神经元的结构如下图所示:

1943年,心理学家沃伦·麦卡洛克(Warren McCulloch)和数理逻辑学家沃尔特·皮茨(Walter Pitts)通过对生物神经元的研究,提出了模拟生物神经元机制的人工神经网络的数学模型,这一成果被美国神经学家弗兰克·罗森布拉特(Frank Rosenblatt)进一步发展成感知机(Perceptron)模型,这也是现代深度学习的基石。

我们从神经元的结构出发,来模拟这个神经元的信号处理过程。

如下图a所示,神经元输入向量\(x=[x_1,x_2,...,x_n]^T\),经过函数映射:\(f_\theta:x->y\)后得到y,其中\(\theta\)为函数f的自身参数。在这里,我们考虑一种简化的情况,也就是线性变换:\(f(x)=w^Tx+b\),因为其中的w和x都是向量,所以我们将其展开为标量形式可表示为:

\[f(x)=w_1x_1 + w_2x_2+...+w_nx_n+b
\]

上述计算的逻辑过程可通过下图b直观展现

以上神经元含有多个输入,为了方便理解,我们不妨进一步简化模型,此时的n=1,即我们假设该线性模型为:

\[y = wx+b
\]

其中\(w\)体现的是模型的斜率,而b体现的是截距,或者在这里我们说是偏置。

我们知道,对于一条直线来讲,我们只需要已知两个点,求解二元一次方程组,就能得到该直线的具体表达式,也就是求解出\(w,b\)的值。

理想状态下的确是这样的,但是现实总是残酷的,我们所获取到的数据可能存在一定的误差,此时我们就根本无法构建出这么一条完美的直线来切合这些数据点。我们不妨用\(\varepsilon\)来表示该观测误差,假设该误差满足\(N(\mu,\sigma^2)\)的高斯分布,则我们的模型可转换为:

\[y = wx+b+\varepsilon,\varepsilon \in N(\mu,\sigma^2)
\]

虽然我们不可能通过一条直线来完美的通过这些数据点,所以我们现在的需求就是尽可能找到这么一条直线,使得所有数据点到这条直线的“距离”最小,那么得到的这条直线就是我们比较满意的模型。

那么如何衡量所有数据点到达这条直线的“距离”最小?如何衡量这个模型的“好”与“不好”呢?这个时候就需要引出我们的损失函数了,一个很自然的想法就是求出当前模型的所有采样点上的预测值与真实值之间差的平方和的均值来作为这个模型的损失函数,也就是我们常常所提到的均方误差,损失函数\(L\)表达如下:

\[L=\frac{1}{n}\sum_{i=1}^n(wx^{(i)}+b-y^{(i)})^2
\]

当我们的损失函数计算的值比较大的时候,此时说明该直线的拟合效果并不好,当我们的损失函数计算的值比较小的时候,说明此时的拟合效果达到了一个不错的程度。所以,我们不妨令损失函数值达到最小时,此时的模型参数为\(w^*,b^*\),则为:

读到这里,各位看官是不是知道下文如何走笔的了。没错,接下来就是通过梯度下降算法来求解该损失函数的最小值,

对此,我们需要求解出损失函数分别对\(w,b\)的偏导,求解过程如下:

即:

\[\begin{aligned}
& \frac{\partial L}{\partial w}=\frac{2}{n}\sum_{i=1}^n(wx^{(i)}+b-y^{(i)})x^{(i)} \\
& \frac{\partial L}{\partial b}=\frac{2}{n}\sum_{i=1}^n(wx^{(i)}+b-y^{(i)})
\end{aligned}
\]

得到偏导之后,我们就可以根据旧的\(w,b\)更新得到新的\(w,b\),这就是一次更新迭代过程。更新之后,我们再次重新计算偏导并更新参数,如此不断循环往复,知道我们计算的损失函数的值得到一个我们可接受的范围,即达到了我们的目的。

下面,我们通过代码来模拟实现这个过程。

  • NumPy随机生成数据集,并通过Matplotlib初步观察数据的分布
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 用于生成样本数据
Return:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
"""
def establish_data(data_number):
x_data = np.random.uniform(-10, 10, data_number)
eps = np.random.normal(0, 1, data_number)
y_data = x_data * 1.474 + 0.86 + eps
return x_data, y_data if __name__ == "__main__":
x_data, y_data = establish_data(100)
from matplotlib import pyplot as plt
plt.scatter(x_data, y_data)
plt.show()

运行结果如下,可以看出数据分布大致可通过一条直线来进行拟合:

  • 根据数据和当前的w、b值计算均方误差
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 计算均方误差
Parameters:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
w_now: 当前的w参数
b_now: 当前的b参数
Return:
mse_value: 均方误差值
"""
def calc_mse(x_data, y_data, w_now, b_now):
x_data, y_data = np.mat(x_data), np.mat(y_data)
_, data_number = x_data.shape
return np.power(w_now * x_data + b_now - y_data, 2).sum() / float(data_number)
  • 单次对w、b参数进行更新迭代
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 更新迭代一次w、b
Parameters:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
w_now: 当前的w参数
b_now: 当前的b参数
learning_rate: 学习率
Return:
w_new: 更新迭代之后的w
b_new: 更新迭代之后的b
"""
def step_gradient(x_data, y_data, w_now, b_now, learning_rate):
x_data, y_data = np.mat(x_data), np.mat(y_data)
w = (w_now * x_data + b_now - y_data) * x_data.T * 2 / x_data.shape[1]
b = (w_now * x_data + b_now - y_data).sum() * 2 / x_data.shape[1]
return w_now - w * learning_rate, b_now - b * learning_rate
  • 多次迭代更新w、b(外循环)
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 多次迭代更新w、b(外循环)
Parameters:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
starting_w: 初始的w参数
starting_b: 初试的b参数
learning_rate: 学习率
max_iter:最大迭代次数
Return:
w:得到的最终w
b: 得到的最终b
loss_list: 每次迭代计算的损失值
"""
def gradient_descent(x_data, y_data, starting_b, starting_w, learning_rate, max_iter):
b, w = starting_b, starting_w
loss_list = list()
for step in range(max_iter):
w, b = step_gradient(x_data, y_data, w, b, learning_rate)
loss = calc_mse(x_data, y_data, w, b)
loss_list.append(loss)
return w, b, np.array(loss_list)
  • 拟合结果的可视化
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 拟合结果的可视化
Parameters:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
w: 拟合得到的模型w参数
b: 拟合得到的模型b参数
loss_list: 每次更新迭代得到的损失函数的值
"""
def plot_result(x_data, y_data, w, b, loss_list):
from matplotlib import pyplot as plt
%matplotlib inline plt.subplot(2, 1, 1)
plt.scatter(x_data, y_data)
x_line_data = np.linspace(-10, 10, 1000)
y_line_data = x_line_data * w + b
plt.plot(x_line_data, y_line_data, "--", color = "red") plt.subplot(2, 1, 2)
plt.plot(np.arange(loss_list.shape[0]), loss_list)
plt.show()

程序运行结果如下:

从上方的运行结果来看,我们可以分析得到线性回归模型的拟合效果还不错,完全能够体现出数据的分布规律。另外,通过损失函数的变化图以及具体数值,我们可以观察到,前期损失值的变化非常的大,到了后期基本居于平缓,看比如说第一次到后面计算的损失值分别为14.215、4.0139、1.941188.....,这就是梯度下降法所体现出来的效果,也就是说我们的损失函数值越大,我们梯度下降法优化的效果也就越明显。

完整代码:

import numpy as np

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 用于生成样本数据
Return:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
"""
def establish_data(data_number):
x_data = np.random.uniform(-10, 10, data_number)
eps = np.random.normal(0, 1, data_number)
y_data = x_data * 1.474 + 0.86 + eps
return x_data, y_data """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 计算均方误差
Parameters:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
w_now: 当前的w参数
b_now: 当前的b参数
Return:
mse_value: 均方误差值
"""
def calc_mse(x_data, y_data, w_now, b_now):
x_data, y_data = np.mat(x_data), np.mat(y_data)
_, data_number = x_data.shape
return np.power(w_now * x_data + b_now - y_data, 2).sum() / float(data_number) """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 更新迭代一次w、b
Parameters:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
w_now: 当前的w参数
b_now: 当前的b参数
learning_rate: 学习率
Return:
w_new: 更新迭代之后的w
b_new: 更新迭代之后的b
"""
def step_gradient(x_data, y_data, w_now, b_now, learning_rate):
x_data, y_data = np.mat(x_data), np.mat(y_data)
w = (w_now * x_data + b_now - y_data) * x_data.T * 2 / x_data.shape[1]
b = (w_now * x_data + b_now - y_data).sum() * 2 / x_data.shape[1]
return w_now - w * learning_rate, b_now - b * learning_rate """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 多次迭代更新w、b(外循环)
Parameters:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
starting_w: 初始的w参数
starting_b: 初试的b参数
learning_rate: 学习率
max_iter:最大迭代次数
Return:
w:得到的最终w
b: 得到的最终b
loss_list: 每次迭代计算的损失值
"""
def gradient_descent(x_data, y_data, starting_b, starting_w, learning_rate, max_iter):
b, w = starting_b, starting_w
loss_list = list()
for step in range(max_iter):
w, b = step_gradient(x_data, y_data, w, b, learning_rate)
loss = calc_mse(x_data, y_data, w, b)
loss_list.append(loss)
return w, b, np.array(loss_list) """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 拟合结果的可视化
Parameters:
x_data: 数据样本的一个属性
y_data: 数据样本的另一个属性
w: 拟合得到的模型w参数
b: 拟合得到的模型b参数
loss_list: 每次更新迭代得到的损失函数的值
"""
def plot_result(x_data, y_data, w, b, loss_list):
from matplotlib import pyplot as plt
%matplotlib inline plt.subplot(2, 1, 1)
plt.scatter(x_data, y_data)
x_line_data = np.linspace(-10, 10, 1000)
y_line_data = x_line_data * w + b
plt.plot(x_line_data, y_line_data, "--", color = "red") plt.subplot(2, 1, 2)
plt.plot(np.arange(loss_list.shape[0]), loss_list)
plt.show() if __name__ == "__main__":
x_data, y_data = establish_data(100)
w, b, loss_list = gradient_descent(x_data, y_data, 0, 0, 0.01, 1000)
plot_result(x_data, y_data, w[0, 0], b, loss_list)

以上就是本文线性回归的全部内容了,总体上来讲还是挺简单的,难度系数也没那么大,更多关于线性回归的内容,我们后面再来讲解。

这里我们对线性回归做一个简单的总结:

优点:结果比较容易理解,计算上并不复杂,没有太多复杂的公式和花里胡哨的内容

缺点:对非线性的数据拟合不好,时间复杂度还有一定的优化空间

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

我是Taoye,爱专研,爱分享,热衷于各种技术,学习之余喜欢下象棋、听音乐、聊动漫,希望借此一亩三分地记录自己的成长过程以及生活点滴,也希望能结实更多志同道合的圈内朋友,更多内容欢迎来访微信公主号:玩世不恭的Coder。

我们下期再见,拜拜~~~

参考资料:

[1] 《机器学习实战》:Peter Harrington 人民邮电出版社

[2] 《TensorFlow深度学习》:龙龙老师

[3]梯度下降算法原理讲解:https://blog.csdn.net/qq_41800366/article/details/86583789

推荐阅读

《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该恰好瓜还是恰坏瓜

《Machine Learning in Action》—— 女同学问Taoye,KNN应该怎么玩才能通关

《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非线性支持向量机

《Machine Learning in Action》—— hao朋友,快来玩啊,决策树呦

《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”

《Machine Learning in Action》—— 剖析支持向量机,优化SMO

《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM

print( "Hello,NumPy!" )

干啥啥不行,吃饭第一名

Taoye渗透到一家黑平台总部,背后的真相细思极恐

《大话数据库》-SQL语句执行时,底层究竟做了什么小动作?

《Machine Learning in Action》—— 浅谈线性回归的那些事的更多相关文章

  1. 《Machine Learning in Action》—— Taoye给你讲讲Logistic回归是咋回事

    在手撕机器学习系列文章的上一篇,我们详细讲解了线性回归的问题,并且最后通过梯度下降算法拟合了一条直线,从而使得这条直线尽可能的切合数据样本集,已到达模型损失值最小的目的. 在本篇文章中,我们主要是手撕 ...

  2. 学习笔记之机器学习实战 (Machine Learning in Action)

    机器学习实战 (豆瓣) https://book.douban.com/subject/24703171/ 机器学习是人工智能研究领域中一个极其重要的研究方向,在现今的大数据时代背景下,捕获数据并从中 ...

  3. K近邻 Python实现 机器学习实战(Machine Learning in Action)

    算法原理 K近邻是机器学习中常见的分类方法之间,也是相对最简单的一种分类方法,属于监督学习范畴.其实K近邻并没有显式的学习过程,它的学习过程就是测试过程.K近邻思想很简单:先给你一个训练数据集D,包括 ...

  4. 【机器学习实战】Machine Learning in Action 代码 视频 项目案例

    MachineLearning 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远 Machine Learning in Action (机器学习实战) | ApacheCN(apa ...

  5. 机器学习实战(Machine Learning in Action)学习笔记————10.奇异值分解(SVD)原理、基于协同过滤的推荐引擎、数据降维

    关键字:SVD.奇异值分解.降维.基于协同过滤的推荐引擎作者:米仓山下时间:2018-11-3机器学习实战(Machine Learning in Action,@author: Peter Harr ...

  6. 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据

    机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...

  7. 机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集

    机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集 关键字:FPgrowth.频繁项集.条件FP树.非监督学习作者:米 ...

  8. 机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析

    机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析 关键字:Apriori.关联规则挖掘.频繁项集作者:米仓山下时间:2018 ...

  9. 机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记

    机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记 关键字:k-均值.kMeans.聚类.非监督学习作者:米仓山下时间: ...

随机推荐

  1. 第4章 Function语意学

    第4章 Function语意学 目录 第4章 Function语意学 4.1 Member的各种调用方式 Nonstatic Member Function(非静态成员函数) virtual Memb ...

  2. mysql存储过程加事务

    create procedure sp_sw2() begin declare error int default 0; declare continue handler for SQLEXCEPTI ...

  3. linux中配置yum文件

    yum简介:yum的宗旨是自动化地升级,安装/移除rpm包,收集rpm包的相关信息,检查依赖性并自动提示用户解决. yum的关键之处是要有可靠的repository,顾名思义,这是软件的仓库,它可以是 ...

  4. java小工具,使用Swing展示左树右表结构

    代码直接上: 入口类 import java.io.File; import java.util.ArrayList; import java.util.List; import org.json.J ...

  5. [MIT6.006] 19. Daynamic Programming I: Fibonacci, Shortest Path 动态规划I:斐波那契,最短路径

    这节课讲动态规划的内容,动态规划是一种通用且有效的算法设计思路,它的主要成分是"子问题"+"重用".它可以用于斐波那契和最短路径等问题的求解上. 一.斐波那契 ...

  6. 【JVM第七篇】执行引擎

    写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 执行引擎是Java虚拟机中的核心组成部分. 执行引擎的作用就是解析虚拟机字节码指令, ...

  7. tcp syn-synack-ack 服务端接收ack

    TCP 服务端 接收到ack tcp_v4_rcv() -> tcp_v4_do_rcv() -> tcp_v4_hnd_req() + tcp_child_process()tcp_v4 ...

  8. IP 层收发报文简要剖析6--ip_forward 报文转发

    //在函数ip_route_input_slow->ip_mkroute_input注册, /* * IP数据包的转发是由ip_forward()处理,该函数在ip_rcv_finish() * ...

  9. kernel 目录

    1. 直接控制硬件 arch : Soc 相关 drivers : 硬件驱动 2. block: 块设备操作逻辑 kernel : 内核实现 net mm  : 内存管理 fs : 各种文件系统实现 ...

  10. 开发工具之Git(一)

    目录 一.什么是Git 二.Git基本原理 三.Git用户交互 一.什么是Git 答:Git是一个分布式版本控制软件.另外提一句,它的开发者就是大名鼎鼎的Linux之父Linus. 版本控制,顾名思义 ...