第四章 训练模型

线性模型(Linear Regression)

线性模型的一般形式如下

y^=θ0+θ1x1+θ2x2+…+θnxn\hat{y} = \theta_0 + \theta_1 x_1 + \theta_2 x_2 + … + \theta_n x_ny^​=θ0​+θ1​x1​+θ2​x2​+…+θn​xn​

  • y^\hat{y}y^​ 预测结果
  • nnn 特征数量
  • xix_ixi​ 第 iii 个特征值
  • θj\theta_jθj​ 是第 jjj 个模型参数(包括偏置项和特征圈子 θ1,θ2,…,θn)\theta_1, \theta_2,…,\theta_n)θ1​,θ2​,…,θn​)

用矢量形式描述如下

y^=hθ(X)=θ⋅X\hat{y} = h_{\theta}(X) = \theta \cdot Xy^​=hθ​(X)=θ⋅X

  • θ\thetaθ 模型的参数矢量,包含偏置项和特征值权重 θ1−θn\theta_1-\theta_nθ1​−θn​
  • XXX 实例的特征矢量,包含 x0x_0x0​ 到 xnx_nxn​,其中 x0x_0x0​ 始终置为1
  • θ×X\theta \times Xθ×X 是两个矢量的乘积,按照线性代数计算展开是 θ0+θ1x1+θ2x2+…+θnxn\theta_0 + \theta_1 x_1 + \theta_2 x_2 + … + \theta_n x_nθ0​+θ1​x1​+θ2​x2​+…+θn​xn​
  • hθh_{\theta}hθ​是假设函数

正则方程(the Normal Equation)

求解最小化代价函数的 θ\thetaθ 值,有一个闭合解(closed-form solution),换句话说,可以通过数学公式直接计算得到结果,这个公式叫做正规方程(Normal Equation)

θ^=(XTX)−1XTy\hat{\theta} = (X^T X)^{-1} X^T yθ^=(XTX)−1XTy

  • θ^\hat{\theta}θ^ 是最小化代价函数的 θ\thetaθ 值
  • yyy 是包含 y(1)y^{(1)}y(1) 到 y(n)y^{(n)}y(n) 的矢量

让我们生成一些线性的数据来测试这个公式

import numpy as npX = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X] # 添加x0 = 1列
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y) # 正规方程计算
theta_best
array([[3.97884872],[2.92718847]])
X_new = np.array([[0], [2]])
X_new_b = np.c_[np.ones((2, 1)), X_new]
y_predict = X_new_b.dot(theta_best)
y_predict
array([[3.97884872],[9.83322566]])
import matplotlib.pyplot as pltplt.plot(X_new, y_predict, "r-")
plt.plot(X, y, "b.")
plt.axis([0, 2, 0, 15])
plt.show()

使用Scikit-Learn来实现线性回归就很简单了

from sklearn.linear_model import LinearRegressionlin_reg = LinearRegression()
lin_reg.fit(X, y)
lin_reg.intercept_, lin_reg.coef_
(array([3.97884872]), array([[2.92718847]]))
lin_reg.predict(X_new)
array([[3.97884872],[9.83322566]])

LinearRegression类是基于scipy.linalg.lstsq()函数(名字是指“标准二乘法(least squares)"),可以直接这样调用

theta_best_svd, residuals, rank, s = np.linalg.lstsq(X_b, y, rcond=1e-6)
theta_best_svd
array([[3.97884872],[2.92718847]])

这个函数计算 θ^=X+y\hat{\theta} = X^+yθ^=X+y ,其中 X+X^+X+ 是 XXX 的伪逆矩阵(穆尔-彭罗斯逆矩阵Moore-Penrose inverse)。你可以使用 np.linalg.pinv()直接计算伪逆矩阵

np.linalg.pinv(X_b).dot(y)
array([[3.97884872],[2.92718847]])

求伪逆矩阵本身采用了一种标准的矩阵因式分解方法叫做奇异值分解(Singular Value Decomposition),这种方法可以把训练数据矩阵 XXX 分解为三个矩阵 U,∑,VTU,\sum, V^TU,∑,VT 的乘积(更多的信息可以查看numpy.linalg.svg())。求伪逆矩阵的计算是 X+=V∑UTX^+=V\sum U^TX+=V∑UT。当 XTXX^TXXTX 不可逆时,正规方程无法求解,而求伪逆矩阵仍然可以在这种情况运行。

计算复杂度(Computational Complexity)

正规方程需要计算 XTXX^TXXTX 的转置,计算复杂度是 (n+1)×(n+1)(n+1)\times(n+1)(n+1)×(n+1)(其中 nnn 是特征数量)。转置一个这种矩阵的计算复杂度一般是 O(n2.4)O(n^{2.4})O(n2.4) 到 O(n3)O(n^3)O(n3)。

Scikit-LearnLinearRegression类采用的SVD方法计算逆的复杂度是 O(n2)O(n^2)O(n2),所以如果特征数变为两倍,则计算耗时变为原来的四倍

正规方程和SVD方法在特征数量变的很大时计算都非常缓慢。但是优点是计算复杂度与训练集实例数量的关系是线性增长的,计算复杂度是 O(m)O(m)O(m) ,所以它们可以高效地处理训练集

梯度下降(Gradient Descent)

梯度下降是一种常用的优化算法,它能够在大范围的问题中找到最优解。梯度下降的思想是迭代微调参数来最小化代价函数。

梯度下降背后的思想是:开始时我们随机选择一个参数的组合(θ0,θ1,......,θn)\left( {\theta_{0}},{\theta_{1}},......,{\theta_{n}} \right)(θ0​,θ1​,......,θn​),计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。我们持续这么做直到找到一个局部最小值(local minimum),因为我们并没有尝试完所有的参数组合,所以不能确定我们得到的局部最小值是否便是全局最小值(global minimum),选择不同的初始参数组合,可能会找到不同的局部最小值。

使用梯度下降方法时,需要确保所以的特征尺度相似,否则梯度下降需要花很长的时间收敛。

批量梯度下降(Batch Gradient Descent)

为了实现梯度下降方法,需要计算每个模型参数 θj\theta_jθj​ 对应代价函数的梯度。这叫做偏导数(partial derivative)。

∂∂θjMSE(θ)=2m∑i=1m(θTx(i)−y(i))xj(i)\frac{\partial}{\partial \theta_j}MSE(\theta)=\frac{2}{m}\sum \limits_{i=1}^m(\theta^Tx^{(i)}-y^{(i)})x_j^{(i)}∂θj​∂​MSE(θ)=m2​i=1∑m​(θTx(i)−y(i))xj(i)​

为可以使用以下公式直接计算所以的偏导数,而不是一个个地计算

∇θMSE(θ)={abcdefghijklmnopqrst}=2mXT(Xθ−y)\nabla_\theta MSE(\theta)= \left\{ \begin{matrix} a & b & c & d & e\\ f & g & h & i & j \\ k & l & m & n & o \\ p & q & r & s & t \end{matrix} \right\}=\frac{2}{m}X^T(X\theta - y)∇θ​MSE(θ)=⎩⎪⎪⎨⎪⎪⎧​afkp​bglq​chmr​dins​ejot​⎭⎪⎪⎬⎪⎪⎫​=m2​XT(Xθ−y)

注意到,这个公式在每个梯度下降迭代需要计算训练集中所有的 XXX!结果就是它在大数据集上十分缓慢。但是,梯度下降在特征维数很多时效果很好,用梯度下降训练一个有数百或数千维数特征的线性回归模型比使用正规方程或SVD(奇异值分解)快很多。

有了梯度下降向量后,当前点在上方,就直接往下方移动。意思就是直接从 θ\thetaθ 中减去 ∇θMSE(θ)\nabla_\theta MSE(\theta)∇θ​MSE(θ)。这里就是学习率登场的时候了:将学习率 η\etaη 与梯度向量相乘来决定下降步长。

θ(nextstep)=θ−η∂θMSE(θ)\theta^{(next step)} = \theta - \eta \partial_\theta MSE(\theta)θ(nextstep)=θ−η∂θ​MSE(θ)

用以上的思想来快速地实现算法

eta = 0.1   # 学习率
n_iterations = 1000
m = 100theta = np.random.randn(2, 1)for iteration in range(n_iterations):gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y)theta = theta -eta * gradientstheta
array([[3.97884872],[2.92718847]])
  • 找到最佳的学习率可以使用网格搜索的方法
  • 迭代次数可以选择很大一个数量,当梯度向量变的很小时终止迭代

收敛速度(Convergence Rate):当代价函数是凸函数,斜率没有突变(例如MSE代价函数), 具有固定学习率的批量梯度下降算法最终会收敛在最优解,但是你或许需要等待一会儿:在一系列根据代价函数的形状定义的 ϵ\epsilonϵ ,需要迭代 O(1/ϵ)O(1/\epsilon)O(1/ϵ) 的次数。如果为了更精确的解将界限(指 ϵ)\epsilon)ϵ) 变小10倍,那么算法或许需要运行10倍于之前的时间。

随机梯度下降(Stochastic Gradient Descent)

随机梯度下降(Stochastic Gradient Descent, SGD)算法每步迭代随机选择一个实例然后仅根据这个实例计算梯度。

  • 因为每次迭代需要操作的数据很少,算法运行得更快
  • 因为每次迭代只需要一个实例,所以可以在大数据集上训练(SGD可以作为外存算法)
  • SGD运行时比较随机,在整体上是逐渐接近最小值,但是它会反复弹跳,随着时间的变化,它会到达最小值附加,但是它不会稳定下来,仍会反复横跳。所以在算法停止运行时,最终的结果很好,但是不是最优解。
  • 当代价函数不平整时,这会让算法跳出局部最优解,所以比起BGD,SGD有更多的机会找到全局最优解

因此随机性帮助跳出局部最优,但是也意味着算法无法稳定在最小值。一种解决的方法是逐渐地减小学习率。步长开始的时候设置的很大(这有助于快速迭代和跳出局部最优),然后步长慢慢变小,然算法在全局最优解稳定。这个步骤类似于模拟退火。每次迭代控制学习率的函数叫做学习计划(learning schedule)

  • 学习率降低的太快,可能会一直陷在局部最优或者甚至未达到局部最优就停滞了
  • 学习率降低的太慢,可能很长一段时间在最优解附近弹跳,如果你很早就终止算法可能会在次优解终止

以下代码是使用了一个简单学习计划的随机梯度下降算法的实现

n_epochs = 50
t0, t1 = 5, 50def learning_schedule(t):return t0 / (t+t1)theta = np.random.randn(2, 1)for epoch in range(n_epochs):for i in range(m):random_index = np.random.randint(m)xi = X_b[random_index:random_index+1]yi = y[random_index:random_index+1]gradients = 2 * xi.T.dot(xi.dot(theta)-yi)eta = learning_schedule(epoch * m + i)theta = theta - eta * gradients
theta
array([[4.01896884],[2.968826  ]])

需要注意的一点是:实例的选择是随机的,一些实例在迭代过程中可能被多次选择而一些实例完全没有被选中。

  • 为了保证参数趋向全局最优解,简单的方法是打乱训练集,然后随机的选择实例。否则可能出现一个标签一个标签的分类。

采用Scikit-LearnSGDRegressor类实现SGD,例子如下所示

from sklearn.linear_model import SGDRegressor
sgd_reg = SGDRegressor(max_iter=1000, tol=1e-3, penalty=None, eta0=0.1)
sgd_reg.fit(X, y.ravel())
SGDRegressor(eta0=0.1, penalty=None)
sgd_reg.intercept_, sgd_reg.coef_
(array([3.89348504]), array([2.86385718]))
sgd_reg
SGDRegressor(eta0=0.1, penalty=None)

小批量梯度下降(Mini-batch Gradient Descent)

Mini-batch GD在小部分的随机数据集实例上计算梯度。Mini-batch GD比起随机梯度下降的主要优点是可以通过硬件矩阵操作的优化获得性能增益,尤其在使用GPU的时候。

  • Mini-batch GD在参数空间的变化比SGD变化少一些不稳定性,尤其是在大数据集下
  • Mini-batch GD比起SGD会更近的靠近最小值
  • Mini-batch GD会更难跳出局部最小值

多元回归(Polynomial Regression)

如果数据实际上比起简单的直线要复杂,也可以使用线性模型来拟合非线性数据。一个简单的方法就是增加特征的幂数,然后在这些扩增的数据特征上训练线性模型,这种技术叫做多元回归。

一个简单的平方等式生成的例子如下

m = 100
X = 6 * np.random.rand(m, 1) -3
y = 0.5 * X**2 + X + 2 + np.random.randn(m, 1)

数据生成了,画图查看数据的分布

plt.scatter(X, y)
plt.xlabel('X_1')
plt.ylabel('y')
plt.show()

很显然,直线不能很好地拟合数据。所以利用Scikit-LearnPolynomialFeatures类来转化和训练数据,为每个特征添加平方项作为新的特征

from sklearn.preprocessing import PolynomialFeatures
poly_features = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly_features.fit_transform(X)
X[0]
array([-2.80664181])
X_poly[0]
array([-2.80664181,  7.87723826])

X_poly现在包含了原来X特征和其对于的平方项特征。现在可以使用LinearRegression模型来拟合这个扩展后的数据集

lin_reg = LinearRegression()
lin_reg.fit(X_poly, y)
lin_reg.intercept_, lin_reg.coef_
(array([2.11424994]), array([[0.98144922, 0.4598956 ]]))
x_pre = np.arange(-4,3,0.01).reshape(-1,1)
x_ppre = poly_features.fit_transform(x_pre)
y_ppre = lin_reg.predict(x_ppre)
plt.scatter(X, y)
plt.plot(x_pre, y_ppre,'r-', label="Predictions")
plt.legend()
plt.xlim(-3, 3)
plt.xlabel("X1")
plt.ylabel("y")
plt.show()

得到的模型是 y^=0.56x12+0.93x1+1.78\hat{y} = 0.56x_1^2+0.93x_1 + 1.78y^​=0.56x12​+0.93x1​+1.78,实际的模型函数是 y=0.5x2+1.0x1+2.0+Gaussiannoisey=0.5x^2 + 1.0x_1+2.0+Gaussian noisey=0.5x2+1.0x1​+2.0+Gaussiannoise

学习曲线(Learning Curves)

实际情况下,模型过于复杂会导致过拟合,模型太简单会出现欠拟合。

第二章中利用交叉验证可以判断模型是过拟合或者欠拟合。

另一种方式是通过学习曲线(learning curves):绘制模型在训练集和测试验证集上的表现。为了生成曲线,简单地在不同大小的训练子集上训练模型。

from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_splitdef plot_learning_curves(model, X, y):X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2)train_errors, val_errors = [], []for m in range(1, len(X_train)):model.fit(X_train[:m], y_train[:m])y_train_predict = model.predict(X_train[:m])y_val_predict = model.predict(X_val)train_errors.append(mean_squared_error(y_train[:m], y_train_predict))val_errors.append(mean_squared_error(y_val, y_val_predict))plt.plot(np.sqrt(train_errors), "r-+", linewidth=2, label="train")plt.plot(np.sqrt(val_errors), "b-", linewidth=3, label="val")
lin_reg = LinearRegression()
plot_learning_curves(lin_reg, X, y)
plt.legend()
plt.show()

# 10th degree 多元线性模型
from sklearn.pipeline import Pipelinepolynomial_regression = Pipeline([("poly_features", PolynomialFeatures(degree=10, include_bias=False)),("lin_reg", LinearRegression()),
])plot_learning_curves(polynomial_regression, X, y)
plt.ylim(0,3)
plt.legend()
plt.show()


该学习曲线和前者很相似,但是两者有两个很重要的不同:

  • 这次的训练数据误差远低于线性回归模型
  • 在两条曲线中间有间隔。这表示模型在训练数据上表现比校验误差好,这是过拟合的标志。但是,如果你用一个更大的数据集,两条曲线之间的间隔会逐渐变小

一种提高过拟合模型的方法是给模型喂更多的训练数据直到验证误差解决训练误差

偏差与方差的权衡: 统计学和机器学习领域很重要的一个理论结果是-模型的泛化误差可以表示为三个不同误差的和

  • 偏差(Bias):这部分的泛化误差来源于错误的假设,例如假设数据是线性的结果数据实际上是二次型的。高偏差的模型绝大多数欠拟合训练数据
  • 方差(Variance):这部分是由于模型对训练数据的小变化的过分敏感。有很高次方自由项的模型(例如高次方的多元线性模型)更有可能有高的方差,然后可能过拟合数据
  • 不可避免误差(Irreducible error):这部分是由于数据本身的噪声。减少这部分误差的唯一方法是清理数据(比如,修复数据源,确实的张量(tensor),或检测和清楚异常值)

增加模型的复杂度通常会提升其方差并降低偏差。相反地,减少模型的复杂度会增加偏差和减少方差,这就是需要考虑权衡的原因。

正则化线性模型(Regularized Linear Models)

降低过拟合的一种方法的是正则化模型:自由度越低,过拟合程度越低。以下是三种不同的限制权重来降低过拟合的方法。

岭回归(Ridge Regression)

代价函数中添加了一个正则项 a∑i=1nθi2a\sum_{i=1}^n\theta_i^2a∑i=1n​θi2​. 正则化项只有在训练中添加,模型训练之后,评估模型的性能则使用未正则化的性能评估方法

岭回归代价函数的公式表示为:

J(θ)=MSE(θ)+a12∑i=1nθi2J(\theta) = MSE(\theta) + a\frac{1}{2}\sum_{i=1}^n\theta_i^2J(θ)=MSE(θ)+a21​i=1∑n​θi2​

需要注意的是 θ0\theta_0θ0​ 没有正则化
在实施岭回归之前,标准化数据很重要,因为岭回归对与输入特征的尺度很敏感

岭回归的闭合解

θ^=(XTX+aA)−1XTy\hat{\theta} = (X^TX+aA)^{-1}X^Tyθ^=(XTX+aA)−1XTy

以下是如何使用Scikit-Learn通过闭合解实现岭回归

from sklearn.linear_model import Ridgeridge_reg = Ridge(alpha=1, solver="cholesky")
ridge_reg.fit(X, y)
Ridge(alpha=1, solver='cholesky')
ridge_reg.predict([[1.5]])
array([[5.0048275]])
# 使用随机梯度下降法
sgd_reg = SGDRegressor(penalty="l2")
sgd_reg.fit(X, y.ravel())
sgd_reg.predict([[1.5]])
array([4.99518164])

套索回归(Lasso Regression)

最小绝对值收敛和选择运算回归(简称Lasso Regression)是线性回归的另一种正则化方法,它使用的是 l1l_1l1​ 范数

*Lasso Regression代价函数

J(θ)=MSE(θ)+a∑i=1n∣θi∣J(\theta) = MSE(\theta) + a \sum_{i=1}^n|\theta_i|J(θ)=MSE(θ)+ai=1∑n​∣θi​∣

from sklearn.linear_model import Lasso
lasso_reg = Lasso(alpha=0.1)
lasso_reg.fit(X, y)
lasso_reg.predict([[1.5]])
array([4.95391855])

弹性网络(Elastic Net)

弹性网络是岭回归和Lasso回归的折中

弹性网络代价函数公式

J(θ)=MSE(θ)+ra∑i=1n∣θi∣+1−r2a∑i=1nθi2J(\theta)=MSE(\theta)+ra\sum_{i=1}^n|\theta_i|+\frac{1-r}{2}a\sum_{i=1}^n\theta_i^2J(θ)=MSE(θ)+rai=1∑n​∣θi​∣+21−r​ai=1∑n​θi2​

  • 岭回归一般作为默认的正则化,但是如果只有很少的特征真的有用,可以使用Lasso或Elastic,因为它们倾向减少无用的特征权重至0
  • 通常情况下,Elastic比Lasso好,因为当数据的特征数比数据实例数多或数个特征有较强关联时,Lasso可能表现的不太稳定。

以下是使用Scikit-LearnElasticNet

from sklearn.linear_model import ElasticNetelastic_net = ElasticNet(alpha=0.1, l1_ratio=0.5)
elastic_net.fit(X, y)
elastic_net.predict([[1.5]])
array([4.95584998])

及时停止(Early Stopping)

在一些正则化迭代学习算法中,在验证集误差达到最小时,及时停止是一个很好的方式

逻辑回归(Logistic Regression)

一些回归算法也可以被用于分类,如果评估到可能性高于50%,那么模型将这个实例划分为这个类,否则划分为另一类

评估可能性

逻辑线性回归不是直接输出结果,而是结果的逻辑

逻辑线性回归评估可能性的公式

p^=hθ(x)=σ(xTθ)\hat{p}=h_{\theta}(x)=\sigma(x^T\theta)p^​=hθ​(x)=σ(xTθ)

σ\sigmaσ 是sigmod function,输出的是0到1的数字,定义如下:

σ(t)=11+exp(−t)\sigma(t)=\frac{1}{1+exp(-t)}σ(t)=1+exp(−t)1​

训练和损失函数(Training and Cost Function)

逻辑回归的损失函数如下(log loss)

J(θ)=−1m∑i=1m[y(i)log(p^(i))+(1−y(i))log(1−p(i)^)]J(\theta)=-\frac{1}{m}\sum_{i=1}^m[y^{(i)}log(\hat{p}^{(i)})+(1-y^{(i)})log(1-\hat{p^{(i)}})]J(θ)=−m1​i=1∑m​[y(i)log(p^​(i))+(1−y(i))log(1−p(i)^​)]

其关于 θj\theta_jθj​ 的偏导式如下所示

∂∂θjJ(θ)=1m∑i=1m(σ(θTx(i))−y(i))xj(i)\frac{\partial}{\partial \theta_j}J(\theta)=\frac{1}{m}\sum_{i=1}^m(\sigma(\theta^Tx^{(i)})-y^{(i)})x_j^{(i)}∂θj​∂​J(θ)=m1​i=1∑m​(σ(θTx(i))−y(i))xj(i)​

通过这个公式,你也可以实现批量梯度下降算法,SGD,Mini-batch GD。

决策边界(Decision Boundaries)

使用鸢尾花数据集来阐述逻辑回归

from sklearn import datasetsiris = datasets.load_iris()
list(iris.keys())
['data','target','frame','target_names','DESCR','feature_names','filename']
X = iris["data"][:, 3:] # petal width
y = (iris["target"] == 2).astype(np.int)

获取了数据集,然后训练逻辑回归模型

from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression()
log_reg.fit(X, y)
LogisticRegression()

查看模型对花瓣宽度从0到3cm的评估

X_new = np.linspace(0, 3, 1000).reshape(-1, 1)
y_proba = log_reg.predict_proba(X_new)
plt.plot(X_new, y_proba[:, 1], "g-", label="Iris-Varigica")
plt.plot(X_new, y_proba[:, 0], label="Not Iris-Virginica")
[<matplotlib.lines.Line2D at 0x7f422f7510f0>]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uIROTzgb-1596532786757)(chap4_files/chap4_72_1.svg)]

Softmax Regression

Sk(x)=xTθ(k)S_k(x)=x^T\theta^{(k)}Sk​(x)=xTθ(k)

Equation 4-20.Softmax function

p^k=σ(s(x))k=exp(sk(x))∑j=1kexp(sk(x))\hat{p}_k = \sigma(s(x))_k = \frac{exp(s_k(x))}{\sum_{j=1}^kexp(s_k(x))}p^​k​=σ(s(x))k​=∑j=1k​exp(sk​(x))exp(sk​(x))​

X = iris["data"][:, (2, 3)]
y = iris["target"]softmax_reg = LogisticRegression(multi_class="multinomial", solver="lbfgs", C=10)
softmax_reg.fit(X, y)

LogisticRegression(C=10, multi_class=‘multinomial’)

softmax_reg.predict([[5, 2]])

array([2])

softmax_reg.predict_proba([[5, 2]])

array([[6.38014896e-07, 5.74929995e-02, 9.42506362e-01]])

参考文献

  1. 《Hands-on Machine Learning with Scikit-Learn, Keras & TensorFlow》(2nd Edition)
  2. github 代码地址

动手学机器学习(第二版)-第四章训练模型相关推荐

  1. 数据结构(C语言)第二版 第四章课后答案

    数据结构(C语言)第二版 第四章课后答案 1~5 B B C A B 6~10 B B C B B 11~15 A B D (C,B) C 1.选择题 (1)串是一种特殊的线性表,其特殊性体现在(B) ...

  2. 《计算机组成原理》第二版第四章课后习题解答

    <计算机组成原理>第四章课后习题解答 本文答案均为网上答案,作者仅将其补全组合在一起,错误之处欢迎指正. 1 .解释下列概念   主存.   辅存.  Cache .  RAM .  SR ...

  3. 计算机科学计算第二版第四章,大连理工大学 计算机科学计算 第四章2.pdf

    大连理工大学 计算机科学计算 第四章2 第4章 插值与逼近 4.2.4 Hermite插 值 4.2.4 Hermite插值 理论和应用中提出的某些插值问题,要求插值函数p (x) 具有一定的光滑度, ...

  4. 性能之巅第二版 第四章 观测工具

    第四章 观测工具 学习目标 认识静态性能工具和危机排查工具 了解工具的类型和工具运行的开销,包括:计数器.剖析工具和跟踪工具 观测工具的来源 工具范围 分为静态性能工具和危机处理工具 工具类型 性能观 ...

  5. 具体数学第二版第四章习题(4)

    46 (1)假设$j^{'}j-k^{'}k=Gcd(j,k)$,那么有$n^{j^{'}j}=n^{k^{'}k}n^{Gcd(j,k)}$,所以如果$n^{j^{'}j}=pm+1,n^{k^{' ...

  6. 机器学习实践—基于Scikit-Learn、Keras和TensorFlow2第二版—第4章 训练模型

    通过之前的学习,我们已经可以创建出手写数字训练的模型,并且经过不断优化能达到一个很好的效果,但是这些模型背后是如何工作,我们却一无所知,就像一个黑盒.深入了解模型背后的原理,可以使我们更快地适应模型. ...

  7. 具体数学第二版第四章习题(1)

    1 令$n=2^{a}3^{b}5^{c}$,它的因子个数为$k=(a+1)(b+1)(c+1)$.所以$k=1,2,3,4,5,6$时对应的$n=1,2,4,6,16,12$ 2 $Gcd(n,m) ...

  8. Javascript高级程序设计第二版第四章--变量,作用域及内存问题--笔记

    由于JavaScript 变量松散类型的本质,决定了它是在特定时间用于保存特定值的一个名字而已,变量的值及其数据类型可以在脚本的生命周期内改变.这可能既有趣又强大,同时又容易出问题. 4.1 语法 E ...

  9. 《快学scala第二版》第一章 练习答案

    1.1 在Scala REPL中键入3.然后按Tab键.有哪些方法可以被应用? 1.2 在Scala REPL中,计算3的平方根,然后再对该值求平方.现在,这个结果与3相差多少?(提示:res变量是你 ...

最新文章

  1. 人力资源部如何运用OKR?看三大层面最新OKR模板
  2. 黑鲨科学计算机,科学技术篇:玩家注意黑鲨一口气发布两款重磅新品
  3. 在winform中使用wpf窗体
  4. 建设IPTV电视系统是否有必要?
  5. 机器学习降维算法四:Laplacian Eigenmaps 拉普拉斯特征映射
  6. js hasChildNodes()指针对元素节点子节点多个的话 true
  7. 字符串数组排序,如果可以保证前一个字符的末尾与后一个字符的开头相同,返回1,否则返回-1...
  8. python手写实现均值滤波_python手写均值滤波
  9. oracle imp指定表空间导入,imp导入其它表空间数据库
  10. 什么是短连接,如何用 Python 生成短连接?
  11. 国开网电大 动物常见病防治 形考任务1-5
  12. 81章 老子1章到_三曜道长解读道德经: 信言不美 第81章
  13. C#实现上位机与PLC通信
  14. 激光雷达的应用及发展前景
  15. 副业搞钱的几个野路子:两个年入10万的零成本赚钱项目
  16. homelede软路由设置方法_二级lede软路由设置方法,lede设置软路由网卡
  17. 开关量无线传输-1主4从
  18. mac pdf去水印_PDF水印工具Mac版
  19. StreamInPut/Output
  20. docker创建(run)容器后容器自动关闭

热门文章

  1. 京东顺丰江湖一战,在所难免!
  2. 服务器虚拟安装linux,迅闪Linux虚拟盘服务器安装全程图解
  3. python flag用法_花了一晚上时间,终于把Python的基本用法归纳好了!
  4. 2个鸡蛋100楼问题
  5. AI真的快让我失业了
  6. 手机号以及区号的正则判断方法
  7. html 输入框自动缩短 一行内显示,当屏幕缩小的时候,第二个input输入框为什么会移到下一行,如何让他在一行显示,自动弹出滚动条?...
  8. JAX计算SeLU函数
  9. 【历史上的今天】4 月 21 日:微处理器先驱诞生;Winamp 发布;COPPA 正式生效
  10. 数字化变电站各层功能