一、决策树(Decision Tree)
- 最大深度(max_depth)
- 含义:决策树的最大深度,它限制了树的生长规模。
- 调参经验:如果树太浅,模型可能会欠拟合,无法很好地捕捉数据中的复杂关系。如果树太深,可能会导致过拟合,模型在训练集上表现很好,但在测试集上性能下降。一般可以从较小的值(如 3 - 5)开始尝试,逐步增加,观察模型在验证集上的性能变化。例如,对于一个简单的二分类数据集,先将
max_depth
设为 3,看准确率等指标,如果准确率较低且有提升空间,再尝试增加到 5 等。
- 最小样本分割(min_samples_split)
- 含义:一个节点在被分割之前必须包含的最小样本数。
- 调参经验:如果这个值设置得过大,树的生长会受到限制,可能导致欠拟合。如果设置得过小,可能会使树过于复杂,容易过拟合。通常可以从默认值(一般是 2)开始调整,逐步增加,如设置为 5、10 等,观察模型性能。
- 最小样本叶节点(min_samples_leaf)
- 含义:叶节点必须包含的最小样本数。
- 调参经验:和
min_samples_split
类似,较小的值可能会使树更复杂,容易过拟合。一般可以根据数据规模来设置,例如对于较小的数据集,可以设置为 1 - 5,对于较大的数据集可以适当增大这个值。
二、随机森林(Random Forest)
- 决策树数量(n_estimators)
- 含义:森林中决策树的数量。
- 调参经验:更多的树通常会使模型更稳定,减少方差,但也会增加计算成本和训练时间。一般可以从一个较小的数(如 100)开始,逐步增加,观察模型性能的变化。例如,每次增加 50 棵树,观察验证集上的准确率、召回率等指标是否有提升。当增加树的数量对性能提升不大时,就可以停止增加。
- 最大特征数(max_features)
- 含义:在构建每棵决策树时,用于寻找最佳分割点的最大特征数量。
- 调参经验:如果设置为 “auto”,则会使用特征总数的平方根作为最大特征数。可以尝试不同的值,如 “log2”(以 2 为底的对数特征数)、特征总数的 1/3 等。较小的值可以降低模型的方差,但可能会增加偏差。
- 其他决策树相关参数
- 随机森林中的决策树部分也可以调参,如
max_depth
、min_samples_split
和min_samples_leaf
等,调参方法和决策树类似。
- 随机森林中的决策树部分也可以调参,如
三、支持向量机(Support Vector Machine,SVM)
- 惩罚参数(C)
- 含义:C 是惩罚系数,用于控制对错误分类样本的惩罚程度。
- 调参经验:较大的 C 会使模型更关注正确分类每个训练样本,可能导致过拟合。较小的 C 会使模型更容忍错误分类,可能导致欠拟合。可以使用对数尺度来尝试不同的值,如等,观察模型在验证集上的准确率和召回率的平衡情况。
- 核函数(kernel)及其参数
- 含义:核函数用于将低维数据映射到高维空间,使得数据在高维空间中更容易线性可分。常用的核函数有线性核(
linear
)、多项式核(poly
)、径向基函数核(rbf
)等。 - 调参经验:
- 对于线性核,没有额外的核参数需要调整。如果数据在原始特征空间中看起来线性可分,或者特征数量非常多,可以先尝试线性核。
- 对于多项式核,需要调整多项式的次数(
degree
)等参数。较高的次数可能会使模型更复杂,容易过拟合。一般可以从 2 - 3 开始尝试。 - 对于径向基函数核,需要调整
gamma
参数。gamma
决定了数据映射到高维空间后的分布情况。较大的gamma
会使模型更关注局部数据,可能导致过拟合,较小的gamma
会使模型更平滑,可能导致欠拟合。可以尝试不同的值,如等。
- 含义:核函数用于将低维数据映射到高维空间,使得数据在高维空间中更容易线性可分。常用的核函数有线性核(
四、逻辑回归(Logistic Regression)
- 正则化参数(C)
- 含义:在逻辑回归中,C 和 SVM 中的惩罚系数类似,用于控制正则化强度。,其中是正则化系数。
- 调参经验:较小的 C 会导致较强的正则化,系数会更接近 0,可能导致欠拟合。较大的 C 会导致较弱的正则化,模型可能会过拟合。可以从 1 开始尝试,然后按照对数尺度调整,如 0.1、10 等,同时观察模型在验证集上的准确率、AUC(Area Under the Curve)等指标。
- 求解算法(solver)
- 含义:逻辑回归有多种求解算法,如
liblinear
、lbfgs
、newton - cg
等。 - 调参经验:
liblinear
适用于小数据集,它在处理 L1 和 L2 正则化时比较高效。lbfgs
和newton - cg
适用于大数据集和多分类问题,但可能对数据的数值特性比较敏感。可以根据数据集的大小和性质来选择合适的求解算法。
- 含义:逻辑回归有多种求解算法,如
五、K 近邻(KNN):
- K 值:决定了邻居的数量。通常从小值开始尝试,如 3、5 等。
六、朴素贝叶斯:
- 通常不需要太多调参,可关注平滑参数 alpha 的设置。
以SCIKIT-LEARN为例 :
1. 决策树(DecisionTreeClassifier)
- max_depth(最大深度)
- 在 Scikit - learn 中的默认值:
None
,表示树会一直生长直到所有叶子节点都是纯的(即只包含一类样本)或者包含的样本数小于min_samples_split
。 - 调参策略:可以使用
GridSearchCV
或RandomizedSearchCV
来搜索合适的值。例如,定义一个参数网格param_grid = {'max_depth': [3, 5, 7, 9, 11]}
,然后使用GridSearchCV
来找到最佳的最大深度。在实际操作中,也可以先尝试绘制树的深度与模型性能(如准确率或 F1 - score)的关系曲线,观察性能开始下降的深度点。
- 在 Scikit - learn 中的默认值:
- min_samples_split(最小分割样本数)
- 默认值:2。
- 调参方式:可以尝试
[2, 5, 10, 15, 20]
这样的参数序列进行调参。例如,通过以下代码片段:
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier
param_grid = {'min_samples_split': [2, 5, 10, 15, 20]}
dtc = DecisionTreeClassifier()
grid_search = GridSearchCV(dtc, param_grid, cv = 5)
grid_search.fit(X_train, y_train)
其中X_train
和y_train
是训练数据和标签,cv = 5
表示 5 折交叉验证,这样可以找到使模型在验证集上性能最好的min_samples_split
值。
- min_samples_leaf(最小叶节点样本数)
- 默认值:1。
- 调参考虑:如果数据集较小,可尝试
[1, 2, 3, 4, 5]
这些较小的值;对于较大数据集,可以适当增大范围,如[10, 20, 30, 40, 50]
。在调整这个参数时,同样可以使用交叉验证和参数搜索工具来找到最优值。
2. 随机森林(RandomForestClassifier)
- n_estimators(决策树数量)
- 默认值:100。
- 调参技巧:可以逐步增加
n_estimators
的值,例如从 100 开始,每次增加 50,像[100, 150, 200, 250, 300]
,同时观察模型在验证集上的性能变化。使用RandomizedSearchCV
时可以这样设置参数范围:
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import RandomizedSearchCV
param_dist = {'n_estimators': range(100, 501, 50)}
rfc = RandomForestClassifier()
random_search = RandomizedSearchCV(rfc, param_distributions = param_dist, cv = 5)
random_search.fit(X_train, y_train)
- max_features(最大特征数)
- 默认值:
auto
(自动设置为特征总数的平方根)。 - 调参探索:可以尝试不同的策略,如
'sqrt'
(平方根)、'log2'
(以 2 为底的对数)、None
(使用所有特征)以及一个具体的整数(如特征总数的 1/3 对应的整数)。通过以下代码可以比较不同max_features
设置下的模型性能:
- 默认值:
param_dist = {'max_features': ['sqrt', 'log2', None, 5]}
rfc = RandomForestClassifier()
random_search = RandomizedSearchCV(rfc, param_distributions = param_dist, cv = 5)
random_search.fit(X_train, y_train)
并且,随机森林中的决策树相关参数(如max_depth
、min_samples_split
和min_samples_leaf
)也可以按照决策树调参的方法进行调整,因为随机森林是由多个决策树组成的。
3. 支持向量机(SVC)
- C(惩罚参数)
- 默认值:1.0。
- 调参路径:可以使用对数尺度来搜索合适的 C 值,如
[0.001, 0.01, 0.1, 1, 10, 100]
。在 Scikit - learn 中可以这样进行调参:
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
param_grid = {'C': [0.001, 0.01, 0.1, 1, 10, 100]}
svc = SVC(kernel = 'rbf')
grid_search = GridSearchCV(svc, param_grid, cv = 5)
grid_search.fit(X_train, y_train)
- kernel(核函数)及其参数
- 线性核(linear):没有额外参数需要调整。如果数据在原始特征空间中看起来线性可分,或者特征数量非常多,可以先尝试线性核,通过设置
kernel = 'linear'
来使用。 - 多项式核(poly):
- degree(多项式次数):默认值是 3。可以尝试
[2, 3, 4, 5]
这样的范围进行调参。例如:
- degree(多项式次数):默认值是 3。可以尝试
- 线性核(linear):没有额外参数需要调整。如果数据在原始特征空间中看起来线性可分,或者特征数量非常多,可以先尝试线性核,通过设置
param_grid = {'C': [0.1, 1, 10], 'kernel': ['poly'], 'degree': [2, 3, 4, 5]}
svc = SVC()
grid_search = GridSearchCV(svc, param_grid, cv = 5)
grid_search.fit(X_train, y_train)
- 径向基函数核(rbf):
- gamma(核系数):默认值是
'scale'
或'auto'
。可以尝试不同的值,如[0.001, 0.01, 0.1, 1, 10]
。在 Scikit - learn 中,调参代码如下:
- gamma(核系数):默认值是
param_grid = {'C': [0.1, 1, 10], 'kernel': ['rbf'], 'gamma': [0.001, 0.01, 0.1, 1, 10]}
svc = SVC()
grid_search = GridSearchCV(svc, param_grid, cv = 5)
grid_search.fit(X_train, y_train)
4. 逻辑回归(LogisticRegression)
- C(正则化参数)
- 默认值:1.0。
- 调参方法:可以从 1 开始,按照对数尺度尝试不同的值,如
[0.01, 0.1, 1, 10, 100]
。使用GridSearchCV
进行调参的示例如下:
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
param_grid = {'C': [0.01, 0.1, 1, 10, 100]}
lr = LogisticRegression()
grid_search = GridSearchCV(lr, param_grid, cv = 5)
grid_search.fit(X_train, y_train)
- solver(求解算法)
- 默认值:
lbfgs
。 - 调参考虑:如果数据集较小且使用 L1 正则化,
liblinear
可能是一个好的选择;如果是大数据集和多分类问题,lbfgs
或newton - cg
可能更合适。可以通过改变solver
参数并观察模型训练时间和性能来选择合适的求解算法。例如:
- 默认值:
solvers = ['liblinear', 'lbfgs', 'newton - cg']
for solver in solvers:
lr = LogisticRegression(solver = solver)
lr.fit(X_train, y_train)
score = lr.score(X_test, y_test)
print(f"Using solver {solver}, the test score is {score}")
以TORCH为例:
在使用 torch
库进行分类算法调参时,以下是一些经验:
-
神经网络模型的层数和神经元数量:
- 开始时,可以先构建一个较浅且神经元数量较少的网络,比如 2 - 3 层,每层 32 - 64 个神经元。
- 逐渐增加层数和神经元数量,观察验证集准确率的变化。但要注意避免网络过于复杂导致过拟合。
-
学习率(
lr
):- 这是一个非常关键的参数。常见的起始值可以是 0.001 、 0.01 或 0.1 。
- 如果训练初期损失不下降或波动很大,可能是学习率过大;如果损失下降非常缓慢,可能学习率过小。
- 可以使用学习率调度器,如
StepLR
、ReduceLROnPlateau
等,根据训练情况动态调整学习率。
-
优化器选择:
SGD
(随机梯度下降)简单但可能收敛较慢。Adam
通常在大多数情况下表现良好,能自适应调整学习率。- 可以尝试不同的优化器,观察对模型收敛速度和最终性能的影响。
-
正则化:
L1
和L2
正则化:通过在损失函数中添加正则项来控制模型的复杂度,防止过拟合。可以从较小的正则化系数开始尝试,如 0.001 、 0.01 等,逐渐增加找到合适的值。Dropout
:在训练过程中随机将神经元的输出设置为 0 ,通常Dropout
率可以设置在 0.2 - 0.5 之间。
-
激活函数:
ReLU
是常用的激活函数,但对于某些问题,其他激活函数如Leaky ReLU
、ELU
等可能效果更好。
-
数据增强:
- 如果数据量较小,可以使用数据增强技术,如翻转、旋转、裁剪等,增加数据的多样性。
-
训练轮数(
epochs
):- 太少可能导致模型未充分训练,太多可能导致过拟合。可以先设置一个较大的值,观察损失和准确率的变化,在合适的时候提前停止训练。
-
批大小(
batch_size
):- 一般从 32 、 64 开始尝试,较大的批大小可能加快训练速度,但可能需要更大的内存。较小的批大小可能引入更多的随机性,有助于模型的泛化。
调参是一个不断尝试和优化的过程,需要结合具体的数据和问题来进行。
以下是一个使用 torch
库进行简单神经网络分类任务的调参示例代码,包括了学习率、层数和神经元数量、优化器等方面的调参示例:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision.datasets import MNIST
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader
# 定义神经网络模型
class NeuralNetwork(nn.Module):
def __init__(self, input_dim, hidden_dim, num_classes, num_layers=2):
super(NeuralNetwork, self).__init__()
self.layers = nn.ModuleList()
self.layers.append(nn.Linear(input_dim, hidden_dim))
for _ in range(num_layers - 1):
self.layers.append(nn.Linear(hidden_dim, hidden_dim))
self.out_layer = nn.Linear(hidden_dim, num_classes)
def forward(self, x):
for layer in self.layers:
x = torch.relu(layer(x))
return self.out_layer(x)
# 数据加载和预处理
train_dataset = MNIST(root='data/', train=True, transform=ToTensor(), download=True)
test_dataset = MNIST(root='data/', train=False, transform=ToTensor())
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
# 初始参数设置
input_dim = 784 # MNIST 图像展平后的维度
hidden_dim = 128 # 隐藏层神经元数量
num_classes = 10 # 类别数(0 - 9)
num_layers = 2 # 网络层数
learning_rate = 0.001 # 初始学习率
epochs = 10 # 训练轮数
# 模型初始化
model = NeuralNetwork(input_dim, hidden_dim, num_classes, num_layers)
# 优化器选择
optimizer = optim.SGD(model.parameters(), lr=learning_rate) # 初始使用 SGD 优化器
# 损失函数
criterion = nn.CrossEntropyLoss()
# 训练函数
def train(model, optimizer, criterion, train_loader, epochs):
for epoch in range(epochs):
for batch_images, batch_labels in train_loader:
batch_images = batch_images.view(-1, input_dim)
optimizer.zero_grad()
outputs = model(batch_images)
loss = criterion(outputs, batch_labels)
loss.backward()
optimizer.step()
# 在每个 epoch 结束时计算验证准确率
correct = 0
total = 0
with torch.no_grad():
for batch_images, batch_labels in test_loader:
batch_images = batch_images.view(-1, input_dim)
outputs = model(batch_images)
_, predicted = torch.max(outputs.data, 1)
total += batch_labels.size(0)
correct += (predicted == batch_labels).sum().item()
accuracy = correct / total
print(f'Epoch {epoch + 1}, Accuracy: {accuracy}')
# 初始训练
print("Initial Training:")
train(model, optimizer, criterion, train_loader, epochs)
# 调参示例:
# 1. 调整学习率
learning_rate = 0.01 # 将学习率调整为 0.01
optimizer = optim.SGD(model.parameters(), lr=learning_rate) # 更新优化器的学习率
print("Training with adjusted learning rate (0.01):")
train(model, optimizer, criterion, train_loader, epochs)
# 2. 增加网络层数
num_layers = 3 # 将网络层数增加到 3
model = NeuralNetwork(input_dim, hidden_dim, num_classes, num_layers) # 重新初始化模型
optimizer = optim.SGD(model.parameters(), lr=learning_rate) # 重新设置优化器
print("Training with increased number of layers (3):")
train(model, optimizer, criterion, train_loader, epochs)
# 3. 更换优化器为 Adam
optimizer = optim.Adam(model.parameters(), lr=learning_rate) # 使用 Adam 优化器
print("Training with Adam optimizer:")
train(model, optimizer, criterion, train_loader, epochs)
在上述代码中,可以通过修改学习率、网络层数和优化器等参数,并观察不同参数设置下模型在验证集上的准确率,来体会调参对模型性能的影响。实际应用中,还可以进一步调整其他参数,如隐藏层神经元数量、正则化参数、批大小等。