入门(选修):《深度学习详解》(Datawhale X 李宏毅苹果书 AI夏令营)

前言 

文章概述《深度学习详解》- 3.6

书中介绍了深度学习中的几个核心概念和技术,包括动量(momentum)、均方根(sigma)、分类与回归的关系、softmax函数的应用以及交叉熵损失函数的选择。首先,动量和均方根都是用于调整学习率的技巧,尽管它们都考虑了过去的梯度信息,但动量关注的是梯度的方向而均方根则只考虑梯度的大小。其次,文章讨论了分类与回归的基本区别及联系,并通过独热编码方式解决了类别标识问题。接着,详细介绍了softmax函数的作用,即通过将输出归一化到0到1之间并突出最大值,使得模型能够进行概率分类。此外,文中还探讨了交叉熵作为分类问题的标准损失函数,相比于均方误差,交叉熵能更好地指导模型收敛至全局最优解。最后,提出了批量归一化(Batch Normalization, BN)技术,旨在改善模型训练过程中的梯度消失或爆炸问题,从而提高模型训练效率和性能。通过对这些关键技术和概念的阐述,文章提供了深度学习中常见问题的有效解决方案,有助于读者理解深度学习模型的工作原理及其优化策略。


个人学习笔记以及概念梳理,望对大家有所帮助。


思维导图3.6

分类优化算法(补充)

涉及的一些术语

术语

解释

分类 (Classification)

一种监督学习任务,其目标是将输入数据分配到预定义的类别中。

回归 (Regression)

一种监督学习任务,其目的是预测连续值的目标变量。

独热向量 (One-Hot Vector)

一种表示分类变量的方法,其中每个类别对应向量中的一个元素,只有一个元素为1,其余均为0。

Softmax 函数

一种激活函数,用于将向量转换为概率分布,使得每个元素在0到1之间,并且所有元素之和为1。

Sigmoid 函数

一种激活函数,常用于二分类问题,输出介于0到1之间,可以视为概率。

交叉熵 (Cross Entropy)

一种损失函数,用于衡量模型预测的概率分布与真实分布之间的差异。最小化交叉熵相当于最大化模型的似然性。

批量归一化 (Batch Normalization, BN)

一种正则化技术,通过对每一批数据进行归一化处理,以加速训练过程并提高模型性能。

均方根 (Root Mean Square, RMS)

在优化器中使用,通过平方梯度来衡量梯度的大小,而不考虑方向。

学习过程遇到的一些问题的理解:

1分类问题中的损失函数选择


选择建议:

数据平衡性:如果数据集类别分布相对均衡,可以选择二元交叉熵。

模型类型:如果是支持向量机,通常使用 Hinge 损失。

类别不平衡:在处理类别不平衡的问题时,考虑使用焦点损失。

模型解释性:如果需要较强的模型解释性,可以考虑使用 Hinge 损失和支持向量机。

代码运行

仿 实践(DNN)深度神经网络-分类任务   (详情可见,Docs (feishu.cn) )


Urbansound8K 是目前应用较为广泛的用于自动城市环境声分类研究的公共数据集。本文获取部分为标记的数据集,展示从标记数据到成功分类的全过程。

其中人工初步处理后数据集一共包含1658条已标注的声音片段(<=4s),包含5个分类:"car" "human" "barking" "music" "others"。

注:因为是人工处理,可能对部分声音分类存在个体理解差异,主要是展示声音分类处理的整体过程,精度可能会有所偏差。


实现功能: 将长度为4秒的语音分类为5种:"car" "human" "barking" "music" "others"。

同时输出每一种分类的精度。

处理过程

数据获得:

下载完成后,进行解压,将其中的fold{i}每一个文件夹里的音频移到一个文件夹中。

数据集制作:
 

import os
import librosa
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 定义要读取的目录
directory = r'.\datasets\4s'    #此处修改为先前存储所有视频的文件夹

# 设置 MFCC 参数
n_mfcc = 13  # 提取的 MFCC 数量
hop_length = 512  # 跳跃长度
target_duration = 4  # 目标音频时长(秒)

# 创建一个空列表来存储数据
data = []

# 遍历目录中的所有 .wav 文件
for filename in os.listdir(directory):
    if filename.endswith(".wav"):
        filepath = os.path.join(directory, filename)

        # 使用 librosa 读取音频文件
        y, sr = librosa.load(filepath, sr=None)

        # 检查音频文件的时长是否为4秒
        duration = librosa.get_duration(y=y, sr=sr)
        if abs(duration - target_duration) < 0.1:  # 允许一定的误差范围
            # 提取文件名中的分类信息
            parts = filename.split("-")
            category_code = parts[1]

            # 根据分类信息移动文件到相应的类别文件夹
            if category_code in ["1", "8"]:
                category = "car"
            elif category_code == "2":
                category = "human"
            elif category_code == "3":
                category = "barking"
            elif category_code == "9":
                category = "music"
            else:
                category = "others"  # "car"  "human"  "barking"  "music"  "others"

            # 计算 MFCC 特征
            mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=n_mfcc, hop_length=hop_length)

            # 对每个 MFCC 系数取平均值
            mfccs_mean = np.mean(mfccs, axis=1)

            # 将特征添加到数据列表中
            data.append({
                'filename': filename,
                'class': category,
                **{f'mfcc_{i}': mfcc for i, mfcc in enumerate(mfccs_mean)}
            })

# 创建 Pandas DataFrame
df = pd.DataFrame(data)

# 保存为 CSV 文件
df.to_csv(os.path.join(directory, 'mfcc_dataset.csv'), index=False)

运行后,成功获得数据集,对应列名分别为 'filename' 'class' 'mfcc_0' 'mfcc_1' 'mfcc_2' 'mfcc_3' ... 'mfcc_12' 其中'class' 是对应的类别("car" "human" "barking" "music" "others") 而mfcc_{} 则是 MFCC 系数相关的特征


显示数据集相关数据:

# 加载CSV文件
file_path = './datasets/4s/mfcc_dataset.csv'
data = pd.read_csv(file_path)

#显示前5个数据
print(data.head())

# 计算类别数量
category_counts = data['class'].value_counts()

# 绘制柱状图
plt.figure(figsize=(10, 6))
bars = category_counts.plot(kind='bar', color='skyblue')

# 添加数值标签
for bar in bars.patches:
    # 获取柱子的高度
    height = bar.get_height()
    # 在柱子上方添加文本标签
    plt.text(bar.get_x() + bar.get_width() / 2, height, f'{height}', ha='center', va='bottom')

plt.title('Number of Samples per Class')
plt.xlabel('Class')
plt.ylabel('Number of Samples')
plt.xticks(rotation=0)
plt.tight_layout()  # 自动调整子图参数,使之填充整个图像区域
plt.show()

结果如下:

声音数据类型分布情况

正式开始分类任务:

使用以ReLU 为激活函数的全连接层 (nn.Linear) 构建简单的神经网络来进行分类。

导入包
import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.metrics import classification_report, confusion_matrix, ConfusionMatrixDisplay
import matplotlib.pyplot as plt

数据集相关处理

# 定义数据集类
class AudioDataset(Dataset):
    def __init__(self, features, labels, transform=None):
        self.features = features
        self.labels = labels
        self.transform = transform

    def __len__(self):
        return len(self.features)

    def __getitem__(self, idx):
        feature = self.features[idx]
        label = self.labels[idx]
        if self.transform:
            feature = self.transform(feature)
        return feature, label

# 加载数据集
dataset_path = r'.\datasets\4s\mfcc_dataset.csv'
data = pd.read_csv(dataset_path)

# 提取特征和标签
X = data.drop(['filename', 'class'], axis=1).values
y = data['class']

# 对类别标签进行编码
encoder = LabelEncoder()
y = encoder.fit_transform(y)

# 将标签转换为 one-hot 编码
num_classes = len(np.unique(y))
y = np.eye(num_classes)[y]

# 数据标准化
scaler = StandardScaler()
X = scaler.fit_transform(X)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 转换为 PyTorch 张量
X_train = torch.tensor(X_train, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.long)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_test = torch.tensor(y_test, dtype=torch.long)

# 创建数据集对象
train_dataset = AudioDataset(X_train, y_train)
test_dataset = AudioDataset(X_test, y_test)

# 创建数据加载器
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

定义模型

# 定义模型
class DNN(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(DNN, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, hidden_dim // 2)
        self.fc3 = nn.Linear(hidden_dim // 2, output_dim)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x)
        return x

# 初始化模型
input_dim = X_train.shape[1]
hidden_dim = 128
output_dim = num_classes
model = DNN(input_dim, hidden_dim, output_dim)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

训练模型

# 训练模型
num_epochs = 50
for epoch in range(num_epochs):
    model.train()
    for batch_features, batch_labels in train_loader:
        optimizer.zero_grad()
        # 这里需要将 one-hot 编码的标签转换回整数索引
        batch_labels = torch.argmax(batch_labels, dim=1)
        outputs = model(batch_features)
        loss = criterion(outputs, batch_labels)
        loss.backward()
        optimizer.step()

评估模型
 

# 评估模型
model.eval()
y_true = []
y_pred = []

with torch.no_grad():
    for features, labels in test_loader:
        # 同样地,在测试阶段也需要将 one-hot 编码的标签转换回整数索引
        labels = torch.argmax(labels, dim=1)
        outputs = model(features)
        _, predicted = torch.max(outputs.data, 1)
        y_true.extend(labels.numpy())
        y_pred.extend(predicted.numpy())

# 计算精度和召回率
report = classification_report(y_true, y_pred, target_names=encoder.classes_)
print("Classification Report:")
print(report)

# 绘制混淆矩阵
cm = confusion_matrix(y_true, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=encoder.classes_)
disp.plot()
plt.show()

# 从 classification_report 中提取 Precision 和 F1-Score
report_data = []
lines = report.split('\n')
for line in lines[2:-3]:  # 跳过报告的头部和尾部
    row_data = line.split(' ')
    # 清除空白项
    row_data = [item for item in row_data if item]

    # 检查是否有足够的数据
    if len(row_data) >= 4:
        row = {}
        row['class'] = row_data[0]
        row['precision'] = float(row_data[1].strip('%')) / 100.0
        row['recall'] = float(row_data[2].strip('%')) / 100.0
        row['f1_score'] = float(row_data[3].strip('%')) / 100.0
        report_data.append(row)

# 提取 class names, precision 和 F1-Score
classes = [row['class'] for row in report_data]
precisions = [row['precision'] for row in report_data]
f1_scores = [row['f1_score'] for row in report_data]

# 绘制折线图
plt.figure(figsize=(10, 5))

# 绘制 Precision 折线图
plt.plot(classes, precisions, marker='o', label='Precision', linestyle='--', linewidth=2)

# 绘制 F1-Score 折线图
plt.plot(classes, f1_scores, marker='s', label='F1-Score', linestyle='-', linewidth=2)

# 设置图表标题和坐标轴标签
plt.title('Precision and F1-Score per Class')
plt.xlabel('Class')
plt.ylabel('Score')
plt.legend()

# 显示图表
plt.grid(True)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

运行结果如下:


各类指标图像化

混淆矩阵:

可见,整体的分类效果还是不错的。


这里就不进一步优化, 下面,我们来验证以下内容的情况。

验证

1尝试无dropout下,使用不同的激活函数观察其带来的变化。

 

分析:
ReLU(蓝色):在早期的几个周期内表现最好,但在后续的周期中逐渐下降。

LeakyReLU(橙色):开始时表现良好,但随后逐渐落后于其他激活函数。

Sigmoid(绿色):在整个训练过程中表现最差,可能由于其饱和特性导致梯度消失的问题。

Tanh(红色):在训练初期表现不佳,但在后期逐渐提高并最终超过 LeakyReLU。

Softplus(紫色):开始时表现较差,但在训练过程中逐渐提升,最后超过了除 ReLU 外的所有其他激活函数。

总体来看,Softplus 表现出了较好的稳定性,尽管在早期不如 ReLU 和 Tanh,但它在训练过程中持续改进并在最后达到了最高的准确性。

代码如下:

import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.metrics import classification_report, confusion_matrix
import matplotlib.pyplot as plt

# 定义数据集类
class AudioDataset(Dataset):
    def __init__(self, features, labels, transform=None):
        self.features = features
        self.labels = labels
        self.transform = transform

    def __len__(self):
        return len(self.features)

    def __getitem__(self, idx):
        feature = self.features[idx]
        label = self.labels[idx]
        if self.transform:
            feature = self.transform(feature)
        return feature, label

# 加载数据集
dataset_path = r'.\datasets\4s\mfcc_dataset.csv'
data = pd.read_csv(dataset_path)

# 提取特征和标签
X = data.drop(['filename', 'class'], axis=1).values
y = data['class']

# 对类别标签进行编码
encoder = LabelEncoder()
y = encoder.fit_transform(y)

# 将标签转换为 one-hot 编码
num_classes = len(np.unique(y))
y = np.eye(num_classes)[y]

# 数据标准化
scaler = StandardScaler()
X = scaler.fit_transform(X)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 转换为 PyTorch 张量
X_train = torch.tensor(X_train, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.long)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_test = torch.tensor(y_test, dtype=torch.long)

# 创建数据集对象
train_dataset = AudioDataset(X_train, y_train)
test_dataset = AudioDataset(X_test, y_test)

# 创建数据加载器
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

# 定义模型
class DNN(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim, activation=nn.ReLU()):
        super(DNN, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, hidden_dim // 2)
        self.fc3 = nn.Linear(hidden_dim // 2, output_dim)
        self.activation = activation()

    def forward(self, x):
        x = self.activation(self.fc1(x))
        x = self.activation(self.fc2(x))
        x = self.fc3(x)
        return x

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()

# 记录不同激活函数下的准确率
activations = [nn.ReLU, nn.LeakyReLU, nn.Sigmoid, nn.Tanh, nn.Softplus]
accuracy_history = {activation.__name__: [] for activation in activations}

# 训练模型
num_epochs = 50
input_dim = X_train.shape[1]
hidden_dim = 128
output_dim = num_classes

for activation in activations:
    model = DNN(input_dim, hidden_dim, output_dim, activation)
    optimizer = optim.Adam(model.parameters(), lr=0.001)

    for epoch in range(num_epochs):
        model.train()
        for batch_features, batch_labels in train_loader:
            optimizer.zero_grad()
            # 将 one-hot 编码的标签转换回整数索引
            batch_labels = torch.argmax(batch_labels, dim=1)
            outputs = model(batch_features)
            loss = criterion(outputs, batch_labels)
            loss.backward()
            optimizer.step()

        # 评估模型
        model.eval()
        correct = 0
        total = 0
        with torch.no_grad():
            for features, labels in test_loader:
                # 同样地,在测试阶段也需要将 one-hot 编码的标签转换回整数索引
                labels = torch.argmax(labels, dim=1)
                outputs = model(features)
                _, predicted = torch.max(outputs.data, 1)
                total += labels.size(0)
                correct += (predicted == labels).sum().item()

        accuracy = 100 * correct / total
        accuracy_history[activation.__name__].append(accuracy)
        print(f'Epoch [{epoch+1}/{num_epochs}], Activation: {activation.__name__}, Accuracy: {accuracy:.2f}%')

# 绘制不同激活函数下的准确率变化折线图
plt.figure(figsize=(10, 5))
for activation_name, accuracies in accuracy_history.items():
    plt.plot(range(1, num_epochs + 1), accuracies, label=activation_name)

plt.title('Accuracy over Epochs for Different Activations')
plt.xlabel('Epoch')
plt.ylabel('Accuracy (%)')
plt.legend()
plt.grid(True)
plt.show()

2尝试使用不同的dropout率并观察其对模型预测精度的影响。


 

分析:
Dropout 率为 0.0(蓝色):没有应用 dropout,模型在训练过程中表现出较高的波动性,尤其是在早期的几个周期内,然后逐渐趋于稳定。

Dropout 率为 0.2(橙色):相比于没有 dropout 的情况,该模型在训练过程中更加稳定,虽然初始精度较低,但随着训练的进行,精度逐渐提高。

Dropout 率为 0.4(绿色):与 0.2 相比,精度曲线更平滑,表明模型在训练过程中收敛得更快,而且在训练结束时达到最高精度。

Dropout 率为 0.6(红色):精度曲线仍然保持平稳,但相比之前两种情况,精度稍低一些。

Dropout 率为 0.8(紫色):精度最低,说明过高 dropout 率可能会降低模型的表现。

总的来说,dropout 率为 0.4 的模型在训练过程中表现最优,既避免了过拟合又保持了良好的精度。相比之下,没有 dropout 或者 dropout 率过高的模型都可能导致欠拟合或过拟合问题。

代码如下:

import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.metrics import classification_report, confusion_matrix
import matplotlib.pyplot as plt

# 定义数据集类
class AudioDataset(Dataset):
    def __init__(self, features, labels, transform=None):
        self.features = features
        self.labels = labels
        self.transform = transform

    def __len__(self):
        return len(self.features)

    def __getitem__(self, idx):
        feature = self.features[idx]
        label = self.labels[idx]
        if self.transform:
            feature = self.transform(feature)
        return feature, label

# 加载数据集
dataset_path = r'.\datasets\4s\mfcc_dataset.csv'
data = pd.read_csv(dataset_path)

# 提取特征和标签
X = data.drop(['filename', 'class'], axis=1).values
y = data['class']

# 对类别标签进行编码
encoder = LabelEncoder()
y = encoder.fit_transform(y)

# 将标签转换为 one-hot 编码
num_classes = len(np.unique(y))
y = np.eye(num_classes)[y]

# 数据标准化
scaler = StandardScaler()
X = scaler.fit_transform(X)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 转换为 PyTorch 张量
X_train = torch.tensor(X_train, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.long)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_test = torch.tensor(y_test, dtype=torch.long)

# 创建数据集对象
train_dataset = AudioDataset(X_train, y_train)
test_dataset = AudioDataset(X_test, y_test)

# 创建数据加载器
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

class DNN(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim, activation=nn.ReLU, dropout_rate=0.0):
        super(DNN, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, hidden_dim // 2)
        self.fc3 = nn.Linear(hidden_dim // 2, output_dim)
        self.activation = activation()  # 实例化激活函数
        self.dropout = nn.Dropout(p=dropout_rate)

    def forward(self, x):
        x = self.activation(self.fc1(x))
        x = self.dropout(x)
        x = self.activation(self.fc2(x))
        x = self.dropout(x)
        x = self.fc3(x)
        return x

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()

# 记录不同 dropout 率下的准确率
dropout_rates = [0.0, 0.2, 0.4, 0.6, 0.8]
accuracy_history = {rate: [] for rate in dropout_rates}

# 训练模型
num_epochs = 50
input_dim = X_train.shape[1]
hidden_dim = 128
output_dim = num_classes

for dropout_rate in dropout_rates:
    model = DNN(input_dim, hidden_dim, output_dim, dropout_rate=dropout_rate)
    optimizer = optim.Adam(model.parameters(), lr=0.001)

    for epoch in range(num_epochs):
        model.train()
        for batch_features, batch_labels in train_loader:
            optimizer.zero_grad()
            # 将 one-hot 编码的标签转换回整数索引
            batch_labels = torch.argmax(batch_labels, dim=1)
            outputs = model(batch_features)
            loss = criterion(outputs, batch_labels)
            loss.backward()
            optimizer.step()

        # 评估模型
        model.eval()
        correct = 0
        total = 0
        with torch.no_grad():
            for features, labels in test_loader:
                # 同样地,在测试阶段也需要将 one-hot 编码的标签转换回整数索引
                labels = torch.argmax(labels, dim=1)
                outputs = model(features)
                _, predicted = torch.max(outputs.data, 1)
                total += labels.size(0)
                correct += (predicted == labels).sum().item()

        accuracy = 100 * correct / total
        accuracy_history[dropout_rate].append(accuracy)
        print(f'Epoch [{epoch+1}/{num_epochs}], Dropout Rate: {dropout_rate}, Accuracy: {accuracy:.2f}%')

# 绘制不同 dropout 率下的准确率变化折线图
plt.figure(figsize=(10, 5))
for dropout_rate, accuracies in accuracy_history.items():
    plt.plot(range(1, num_epochs + 1), accuracies, label=f'Dropout Rate: {dropout_rate}')

plt.title('Accuracy over Epochs for Different Dropout Rates')
plt.xlabel('Epoch')
plt.ylabel('Accuracy (%)')
plt.legend()
plt.grid(True)
plt.show()

最后,基于这两个尝试说明
这只是基于特定数据集和网络结构的一个实验结果,实际选择最佳激活函数应根据具体情况而定。在某些情况下,ReLU 可能仍然是更好的选择,因为它简单有效并且计算效率高。此外,还可以考虑其他因素,如过拟合风险、模型复杂性和计算资源等。以及对于其他数据集和模型结构,最优的 dropout 率可能会有所不同。在实践中,建议尝试多种 dropout 率以找到最适合你的任务的最佳值。

补充资料(ChatGBT)



 

小结(实验)

数据集与任务
  • 数据集:使用了UrbanSound8K数据集的一部分,包含了1658条已标注的4秒音频片段,分为5个类别:“car”、“human”、“barking”、“music”和“others”。
  • 任务:对这5类音频进行分类。
数据预处理
  • 使用MFCC(Mel频率倒谱系数)作为特征,提取了13个MFCC系数的平均值。
  • 数据集被划分为训练集和测试集,比例为80%和20%。
模型架构
  • 构建了一个简单的深度神经网络(DNN),包含两层ReLU激活函数的隐藏层和一个输出层。
  • 使用PyTorch框架实现模型,采用Adam优化器和交叉熵损失函数进行训练。
实验结果
  • 在50个epoch的训练后,模型在测试集上表现良好,分类报告展示了各个类别的精确度、召回率和F1分数。
  • 混淆矩阵显示了模型在不同类别间的预测准确性。
补充尝试
  • 尝试无dropout下,使用不同的激活函数观察其带来的变化。
  • 尝试使用不同的dropout率并观察其对模型预测精度的影响。
  • 10
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值