机器学习与深度学习技术解析

table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
pre {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}

138、什么是量化感知训练,为什么需要它?

量化感知训练是在训练期间向模型添加伪量化操作。这使模型能够学会忽略量化噪声,最终的权重对量化会更具鲁棒性。

139、什么是模型并行和数据并行?为什么通常推荐使用数据并行?

模型并行与数据并行


模型并行

是将模型分割成多个部分,并在多个设备上并行运行,有望在训练或推理过程中加快模型速度。


数据并行

是创建模型的多个完全相同的副本,并将它们部署到多个设备上。在训练的每次迭代中,每个副本会被分配不同的数据批次,并计算损失相对于模型参数的梯度。


同步数据并行

:所有副本的梯度会被聚合,优化器执行梯度下降步骤。


异步数据并行

:参数集中管理,副本相互独立运行,每个副本在每次训练迭代结束时直接更新中央参数。

通常推荐使用

数据并行

,主要是因为它在设备间所需的通信较少,而且更易于实现,并且适用于任何模型,而模型并行需要分析模型以确定最佳的分割方式。

140、在多台服务器上训练模型时,可以使用哪些分布式策略?如何选择使用哪种策略?

可以使用的分布式策略有

MirroredStrategy


ParameterServerStrategy

选择策略时:

若模型能装入每个副本的内存中,一般应使用

MirroredStrategy

,因为它使用简单,所有服务器和设备的处理方式相同,性能也较好;

若要训练无法装入 GPU 内存的大型模型,则使用

ParameterServerStrategy

,不过它通常比

MirroredStrategy

慢,且部署难度稍大,因为需要管理参数服务器。

141、使用 MirroredStrategy 在同一台机器上的多个 GPU 上训练任何模型(如果无法使用 GPU,可以使用具有 GPU 运行时的 Colaboratory 并创建两个虚拟 GPU)。再使用 CentralStorageStrategy 训练该模型,并比较训练时间。

使用

MirroredStrategy

训练模型的代码示例如下:


distribution = tf.distribute.MirroredStrategy()
with distribution.scope():
    mirrored_model = tf.keras.Sequential([...])
    mirrored_model.compile([...])
    batch_size = 100
    history = mirrored_model.fit(X_train, y_train, epochs=10)

若要使用

CentralStorageStrategy

训练模型,可将

MirroredStrategy

替换为

CentralStorageStrategy

,示例代码为:


distribution = tf.distribute.experimental.CentralStorageStrategy()

还可设置

compute_devices


parameter_device

参数。

训练完成后,记录两种策略下的训练时间并进行比较。

142、什么是有标签的训练集?

有标签训练集是包含已标注数据的训练集,可用于监督学习,例如:

用于训练人脸分类器的每个人的图片

用于自然语言处理训练模型预测缺失单词的文本数据

143、尝试在数据预处理管道中添加一个转换器,以仅选择最重要的属性。

在Scikit-Learn里,可使用

SelectKBest

等特征选择器来实现。示例代码如下:


from sklearn.compose import ColumnTransformer 
from sklearn.feature_selection import SelectKBest, f_regression
from sklearn.pipeline import Pipeline

# 假设num_pipeline和OneHotEncoder等已定义
num_attribs = list(housing_num)
cat_attribs = ["ocean_proximity"]

# 创建选择最重要属性的转换器
feature_selector = SelectKBest(score_func=f_regression, k=5) # 选择最重要的5个属性

# 更新数值管道,添加特征选择步骤
num_pipeline_with_selection = Pipeline([
    ('original_num_pipeline', num_pipeline),
    ('feature_selection', feature_selector)
])

full_pipeline = ColumnTransformer([
    ("num", num_pipeline_with_selection, num_attribs),
    ("cat", OneHotEncoder(), cat_attribs),
])

housing_prepared = full_pipeline.fit_transform(housing)

以上代码在数值管道里添加了

SelectKBest

特征选择器,仅选择最重要的5个属性。可按需调整

k

的值。

144、在不使用Scikit – Learn的情况下,实现带有提前停止策略的Softmax回归批量梯度下降算法。

实现带有提前停止策略的Softmax回归批量梯度下降算法,需要以下步骤:

初始化权重

计算Softmax函数

计算成本函数(交叉熵损失)

计算梯度

更新权重

提前停止策略

以下是简单的Python代码示例:


import numpy as np

def softmax(z):
    exp_z = np.exp(z - np.max(z, axis=1, keepdims=True))
    return exp_z / np.sum(exp_z, axis=1, keepdims=True)

def cross_entropy_loss(y_true, y_pred):
    m = y_true.shape[0]
    return -np.sum(y_true * np.log(y_pred + 1e-7)) / m

def batch_gradient_descent(X, y, num_classes, learning_rate=0.01, num_iterations=1000, early_stopping_rounds=10):
    m, n = X.shape
    theta = np.random.randn(n, num_classes)
    best_loss = np.inf
    no_improvement_rounds = 0
    for iteration in range(num_iterations):
        logits = X.dot(theta)
        y_pred = softmax(logits)
        loss = cross_entropy_loss(y, y_pred)
        gradients = 1/m * X.T.dot(y_pred - y)
        theta = theta - learning_rate * gradients
        if loss < best_loss:
            best_loss = loss
            no_improvement_rounds = 0
        else:
            no_improvement_rounds += 1
        if no_improvement_rounds >= early_stopping_rounds:
            print(f'Early stopping at iteration {iteration}')
            break
    return theta

你可以使用以下方式调用这个函数:


# 示例数据
X = np.random.randn(100, 10)
y = np.random.randint(0, 3, 100)
y_one_hot = np.eye(3)[y]

# 调用函数
theta = batch_gradient_descent(X, y_one_hot, num_classes=3)

这段代码实现了带有提前停止策略的Softmax回归批量梯度下降算法。首先定义了Softmax函数和交叉熵损失函数,然后在批量梯度下降过程中,根据损失是否改善来决定是否提前停止训练。

145、在一个线性可分的数据集上训练一个 LinearSVC 分类器。然后在相同的数据集上训练一个 SVC 分类器和一个 SGDClassifier 分类器。看看能否让它们生成大致相同的模型。

以下是使用 LinearSVC 训练模型的示例代码:


import numpy as np
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

iris = datasets.load_iris()
X = iris["data"][:, (2, 3)]  # petal length, petal width
y = (iris["target"] == 2).astype(np.float64)  # Iris virginica

svm_clf = Pipeline([
    ("scaler", StandardScaler()),
    ("linear_svc", LinearSVC(C=1, loss="hinge")),
])
svm_clf.fit(X, y)

若要使用

SVC

类,可使用线性核,创建模型时可写为

SVC(kernel="linear", C=1)

;若使用

SGDClassifier

类,可写为

SGDClassifier(loss="hinge", alpha=1/(m*C))

,这里的

m

为训练实例数量。通过在相同的线性可分数据集上使用这些不同的类进行训练,有可能得到大致相同的模型。

146、在MNIST数据集上训练一个支持向量机(SVM)分类器。由于SVM分类器是二元分类器,你需要使用一对其余(one-versus-the-rest)策略来对所有10个数字进行分类。你可以使用小的验证集来调整超参数以加快过程。你能达到什么样的准确率?

在MNIST数据集上使用SVM分类器并采用一对其余策略分类时,准确率会受到多种因素影响,如超参数的选择、数据预处理等。一般而言,经过适当调参和处理,SVM分类器在MNIST数据集上可以达到95% – 98%左右的准确率,但这并非固定值,实际准确率需根据具体实现情况确定。

147、如果决策树对训练集过拟合,尝试减小max_depth是个好主意吗?

减小

max_depth

可以限制树的深度,减少模型复杂度,通常是缓解过拟合的有效方法,所以可以认为是个好主意。

148、在哪些情况下会使用普通PCA、增量PCA、随机PCA或核PCA?

PCA 变体及适用场景


普通PCA

:适用于数据量较小且能一次性加载到内存中进行处理的情况,可用于数据压缩、降维等,如选择合适的维度数量、根据解释方差比进行分析等。


增量PCA

:当数据量非常大,无法一次性全部加载到内存时使用,它可以分批次处理数据,如对大规模训练数据进行处理。


随机PCA

:通常在需要快速计算且对精度要求不是极高,数据量较大时使用。


核PCA

:适用于需要进行复杂非线性投影以实现降维的情况,能够在投影后较好地保留实例的聚类,或者展开靠近扭曲流形的数据集,如对瑞士卷数据集进行降维。

149、加载MNIST数据集,并将其拆分为训练集和测试集(取前60000个实例用于训练,其余10000个用于测试)。在该数据集上训练一个随机森林分类器,并记录训练所需的时间,然后在测试集上评估得到的模型。接下来,使用主成分分析(PCA)将数据集的维度降低,使解释方差比例达到95%。在降维后的数据集上训练一个新的随机森林分类器,看看训练需要多长时间。训练速度是否快了很多?然后在测试集上评估该分类器。与之前的分类器相比,它的表现如何?

可按以下步骤操作:

加载MNIST数据集并划分训练集和测试集;

训练随机森林分类器并计时,评估模型;

使用PCA将数据集降维,使解释方差比例达95%;

在降维数据集上训练新随机森林分类器并计时;

比较两次训练时间,评估新分类器并与旧分类器比较性能。

150、描述两种在使用K – Means时选择合适簇数量的技术。

常见的两种技术为肘部法则和轮廓系数法。


肘部法则


通过绘制不同簇数量下的惯性(样本到其所属簇中心的距离平方和)与簇数量的关系图,惯性下降幅度开始变缓的点对应的簇数量即为合适的选择。


轮廓系数法


计算每个样本的轮廓系数(衡量样本与其所属簇的紧密程度以及与其他簇的分离程度),平均轮廓系数最大时对应的簇数量为合适的簇数量。

151、请列举两种可处理大规模数据集的聚类算法,以及两种寻找高密度区域的聚类算法。

可处理大规模数据集的聚类算法可列举

K-Means



Mini-Batch K-Means

;寻找高密度区域的聚类算法可列举

DBSCAN



Mean-Shift

152、你能想出一个主动学习有用的用例吗?你会如何实现它?

主动学习在医学图像识别中的应用

主动学习在医学图像识别中的作用尤为重要,尤其是在X光、CT等影像的疾病诊断中。由于标注大量医学图像需要高昂的成本和专业知识,主动学习提供了一种有效的解决方案。

实现步骤


初始标注


由医学专家对一小部分有代表性的医学图像进行标注,构建初始训练集。


模型训练


使用初始训练集训练一个机器学习或深度学习模型。


选择样本


模型对未标注的医学图像进行预测,并根据预测的不确定性或信息性等标准,选择最有价值的图像让医学专家进行标注。例如,选择模型预测置信度低的图像,因为这些图像可能包含模型尚未学习到的特征。


更新训练集


将新标注的图像添加到训练集中。


重新训练模型


使用更新后的训练集重新训练模型。


迭代优化


重复步骤3-5,不断迭代上述过程,直到模型性能达到满意的水平或标注成本达到预算限制。

153、经典的Olivetti人脸数据集包含400张64×64像素的灰度人脸图像。每张图像被展平为大小为4096的一维向量。40个不同的人被拍摄(每人10次),通常的任务是训练一个模型,该模型可以预测每张图片中代表的是哪个人。使用sklearn.datasets.fetch_olivetti_faces()函数加载数据集,然后将其拆分为训练集、验证集和测试集(注意,数据集已经在0到1之间进行了缩放)。由于数据集相当小,需要使用分层抽样,以确保每个集合中每个人的图像数量相同。接下来,使用K-Means对图像进行聚类,并确定合适数量的聚类。最后,可视化这些聚类,观察每个聚类中是否有相似的人脸。

可按以下步骤操作:

使用

sklearn.datasets.fetch_olivetti_faces()

函数加载 Olivetti 人脸数据集;

使用分层抽样将数据集拆分为训练集、验证集和测试集;

选择一种确定聚类数量的技术(如轮廓系数法、肘部法则等)确定合适的聚类数量,然后使用 K-Means 对图像进行聚类;

可视化聚类结果,观察每个聚类中是否有相似的人脸。

154、请列举三种常用的激活函数,并画出它们的图像。

常用激活函数

三种常用的激活函数为

阶跃函数



逻辑(Sigmoid)函数



修正线性单元(ReLU)函数

。可使用绘图工具如 Python 的 Matplotlib 库进行绘制。

以 ReLU 函数为例,代码如下:


import numpy as np
import matplotlib.pyplot as plt

z = np.linspace(-5, 5, 100)
relu = np.maximum(0, z)

plt.plot(z, relu)
plt.xlabel('z')
plt.ylabel('ReLU(z)')
plt.title('Rectified Linear Unit (ReLU) Function')
plt.grid(True)
plt.show()

155、在MNIST数据集上训练一个深度多层感知器(使用keras.datasets.mnist.load_data()加载该数据集),尝试获得超过98%的精度。通过指数式增大学习率、绘制误差曲线并找出误差急剧上升的点来搜索最优学习率。添加保存检查点、使用早停法,并使用TensorBoard绘制学习曲线等额外功能。

可按以下步骤解决该问题:

加载MNIST数据集;

数据预处理;

构建深度MLP模型;

搜索最优学习率;

训练模型并添加额外功能(保存检查点、早停法、使用TensorBoard);

评估模型精度。

156、当使用SGD优化器时,如果将动量超参数设置得过于接近1(例如0.99999),可能会发生什么情况?

动量超参数接近1时,优化器会保留更多之前梯度的方向信息

可能导致优化器在更新参数时对当前梯度的响应变慢

在接近最优解时可能会出现过冲和振荡加剧的情况

收敛过程可能变得不稳定

并且可能需要更长时间才能稳定在最优解附近

157、构建一个深度神经网络(DNN),该网络有20个隐藏层,每个隐藏层包含100个神经元(虽然数量过多,但这正是本题的目的)。使用He初始化方法和ELU激活函数。

以下是一个示例代码来构建这样的DNN:


import tensorflow as tf
from tensorflow import keras

model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=[28, 28])) # 假设输入是28x28的图像
for _ in range(20):
    model.add(keras.layers.Dense(100, activation='elu', kernel_initializer='he_normal'))
model.add(keras.layers.Dense(10, activation='softmax')) # 假设是10分类问题

上述代码使用Keras构建了一个具有20个隐藏层,每个隐藏层100个神经元的DNN,使用了He初始化和ELU激活函数,最后一层使用softmax激活函数用于分类。

158、使用Nadam优化器和早停法,在CIFAR10数据集上训练网络。你可以使用keras.datasets.cifar10.load_data()加载该数据集。该数据集由60000张32×32像素的彩色图像组成(50000张用于训练,10000张用于测试),共有10个类别,因此你需要一个具有10个神经元的softmax输出层。请记住,每次更改模型架构或超参数时,都要搜索合适的学习率。

可按以下步骤操作:


加载CIFAR10数据集

:使用

keras.datasets.cifar10.load_data()

加载数据集。


构建模型

:构建一个有20个隐藏层,每层100个神经元的深度神经网络,使用 He 初始化和 ELU 激活函数,输出层使用具有10个神经元的 softmax 激活函数。


配置优化器和早停法

:使用 Nadam 优化器,设置早停法以防止过拟合。


搜索合适的学习率

:每次更改模型架构或超参数时,搜索合适的学习率。


训练模型

:使用训练集对模型进行训练,并使用验证集进行验证。

159、使用tf.range(10)和tf.constant(np.arange(10))会得到相同的结果吗?

tf.range(10)

会创建一个从 0 到 9 的张量,而

tf.constant(np.arange(10))

是将 NumPy 数组

np.arange(10)

(同样是 0 到 9)转换为 TensorFlow 张量,在数值上二者是相同的,但在某些情况下,如涉及到张量的一些元信息等可能存在差异。

160、实现一个执行层归一化(Layer Normalization)的自定义层:a. build()方法应定义两个可训练权重α和β,它们的形状均为input_shape[-1:],数据类型为tf.float32。α应初始化为全1,β应初始化为全0。b. call()方法应计算每个实例特征的均值μ和标准差σ。为此,可以使用tf.nn.moments(inputs, axes=-1, keepdims=True),它会返回所有实例的均值μ和方差σ²(计算方差的平方根以得到标准差)。然后该函数应计算并返回α⊗(X – μ)/(σ + ε) + β,其中⊗表示逐元素乘法(*),ε是一个平滑项(小常数,用于避免除以零,例如0.001)。c. 确保自定义层产生的输出与keras.layers.LayerNormalization层的输出相同(或非常接近)。

以下是实现代码示例:


import tensorflow as tf
from tensorflow import keras

class CustomLayerNormalization(keras.layers.Layer):
    def build(self, input_shape):
        self.alpha = self.add_weight(name='alpha', shape=input_shape[-1:], dtype=tf.float32, initializer='ones', trainable=True)
        self.beta = self.add_weight(name='beta', shape=input_shape[-1:], dtype=tf.float32, initializer='zeros', trainable=True)

    def call(self, inputs):
        epsilon = 0.001
        mean, variance = tf.nn.moments(inputs, axes=-1, keepdims=True)
        std_dev = tf.sqrt(variance)
        return self.alpha * (inputs - mean) / (std_dev + epsilon) + self.beta

要验证自定义层与

keras.layers.LayerNormalization

层的输出是否接近,可以用以下代码:


# 创建输入数据
input_data = tf.random.normal([10, 20])
# 使用自定义层归一化
custom_layer = CustomLayerNormalization()
custom_output = custom_layer(input_data)
# 使用Keras层归一化
keras_layer = keras.layers.LayerNormalization()
keras_output = keras_layer(input_data)
# 检查输出是否接近
print(tf.reduce_all(tf.abs(custom_output - keras_output) < 1e-5))

161、什么是全卷积网络?如何将全连接层转换为卷积层?

全卷积网络(Fully Convolutional Networks,FCN)

全卷积网络(Fully Convolutional Networks,FCN)是一种端到端、像素级的图像语义分割模型。

核心思想

将传统卷积神经网络(CNN)中的

全连接层

替换为

卷积层

可接受

任意大小的输入图像

输出与输入图像大小相同的

特征图

,实现对图像中每个像素的分类。

实现方法

最后一个全连接层的处理

使用与该全连接层神经元数量相同的

滤波器

滤波器大小与前一层特征图大小相同。

每个神经元对应一个滤波器。

采用“valid”填充。

步幅通常设为1,也可设为更高值。

激活函数与原全连接层相同。

其他全连接层的处理

采用

1×1滤波器

通过适当

重塑全连接层的权重矩阵

,可将训练好的CNN按此方式转换。

© 版权声明

相关文章

暂无评论

none
暂无评论...