故障诊断方向而言,无论是信号处理、特征提取、故障分类还是寿命预测,所有的方法实现基本都依靠于Python代码,很多小白遇到的第一个拦路虎便是代码环境的配置。Pytorch是Python第三方库的一种,里面包含很多深度学习机器学习的函数,Pytorch本身有两个版本,一个是简便的CPU版本,一个是高速高效的GPU版本。另外代码编辑器可以直接用于编写、编辑和运行代码。它们提供了代码高亮、自动补全、代码调试、版本控制集成等功能,以提高开发效率和代码质量,也是故障诊断相关代码的必备工具之一。本期给大家带来Pytorch环境(Anaconda)安装教程,并附带代码编辑器配置过程。每一部分内容都附带推荐的视频教程以及教程链接,保证每一位故障诊断学习者都能搭建自己的代码平台。此外,后续文章还手把手带大家跑通第一个故障诊断案例,代码包含数据处理,1DCNN模型搭建,模型训练,以及模型评估等故障诊断完整过程,特别适合研一、研二小白入门。 本期涉及代码非常详细,所占篇幅也非常多,所以分三次呈现给大家,第1篇文章主要介绍主要介绍了Python环境以及各个软件环境安装【初学者必看教程 | 手把手教你安装GPU版Pytorch环境及手把手带大家跑通第一个故障诊断案例!!!(上)】。第2篇文章主要介绍西储大学数据集以及一些所需深度学习基础知识,文章后半部分讲解了本期代码的数据预处理以及数据切割等部分【初学者必看教程| 手把手教你安装GPU版Pytorch环境及手把手带大家跑通第一个故障诊断案例!!!(中)】。本篇为第3篇文章主要构建1DCNN模型框架以及模型训练模型检测等内容。数据集下载:通过点击最左下角的阅读原文进行下载。目录1 引言2 安装Anaconda 2.1 Anaconda介绍 2.2 Anaconda安装3 配置Pytorch环境(CPU版) 3.1 Pytorch介绍 3.2 Pytorch配置教程(CPU版)4 配置Pytorch环境(GPU版) 4.1 两种Pytorch区别(看是否支持GPU) 4.2 CUDA安装 4.3 Pytorch配置教程(GPU版)5 配置代码编辑器 5.1 代码编辑器区别 5.2 VScode编辑器 5.3 Pycharm编辑器 5.4 JupyterNotebook编辑器6 故障诊断代码示例 (重中之重) 6.1 代码介绍 6.2 检验Pytorch 6.3 故障诊断实战代码(模型构建及训练测试部分)注:小编能力有限,如有不恰之处,请多多指正~1 引 言在学习故障诊断相关代码时,拥有一个强大且灵活的开发环境是至关重要的。Anaconda和Pytorch正是这样的工具,它们为我们提供了一个完整的生态系统,用于进行数据分析、模型训练和部署,是目前常用的工具软件资源。虽然网上Anaconda及Pytorch安装教程资源比较丰富,但对一些细节部分,比如在安装GPU版本的Pytorch时,是否需要安装CUDA、以及如何查看CUDA版本等问题上仍存在一些歧义。本文将用通俗易懂的语言及方法带大家了解这些概念,并选择自己最合适的方法。此外,本文提供了下载GPU版Pytorch的快捷方式,以及通俗易懂的视频教程链接,为读者朋友们在安装过程中尽可能带来更多的便利。本期第2篇、第3篇提供了故障诊断实例以及学习代码的必备基础知识,代码包含数据处理,1DCNN模型搭建,模型训练,以及模型评估等故障诊断完整过程,为读者朋友们提供了基本的代码框架。总的来说,本期文章旨在为初学者及入门小白提供一个全面的指南,第1篇科普一些基本概念的同时,提供详细操作过程,帮助大家安装和配置Anaconda环境,以及在该环境中配置Pytorch(包含CPU和GPU两种版本)。此外,本期第2篇、第3篇还带大家学习一个完整故障诊断代码示例,深入学习故障诊断代码的各个框架,为接下来学习打下夯实的基础。无论您是在寻找一个全新的开发环境,还是希望优化现有的工作流程,本期文章都将为您提供必要的指导和资源。6 故障诊断代码示例6.1 代码介绍6.1.1 代码流程数据提取部分代码,把.mat文件中正常数据和12kHz驱动端数据提取成Datafram格式,接着通过预处理将数据划分为长度1024、重叠率0.5的多个样本。并转化为适合深度学习的tensor格式。模型搭建部分构建了1DCNN模型框架,然后模型训练部分调用基本1DCNN模型框架以及训练集验证集通过多次训练生成最佳模型,最后模型测试部分加载最佳模型和测试集并通过准确率,召回率,混淆矩阵等多指标检验模型效果。6.1.2 基础知识6.2 检验Pytorch6.3 故障诊断实战代码6.3.1 数据预处理注:第6节上半部分在上一篇【初学者必看教程| 手把手教你安装GPU版Pytorch环境及手把手带大家跑通第一个故障诊断案例!!!(中)】可查看。6.3.2 模型搭建 该部分定义VGG1DModel 模型,通过 CNN 部分提取输入数据的局部特征,然后通过自适应平均池化层将特征压缩为固定长度的向量,最后通过全连接层将特征映射到分类结果。这种结构适用于处理一维数据的分类任务,能够有效地捕捉数据中的特征并进行分类。代码分成:类定义和初始化、CNN 卷积池化结构构建、前向传播、模型实例化。import torchfrom joblib import dump, loadimport torch.utils.data as Dataimport numpy as npimport pandas as pdimport torchimport torch.nn as nn# 定义VGG-1D模型class VGG1DModel(nn.Module): #类定义和初始化 def __init__(self, batch_size, input_channels, conv_archs, num_classes): super(VGG1DModel, self).__init__() self.batch_size = batch_size # CNN参数 self.conv_arch = conv_archs # 网络结构 self.input_channels = input_channels # 输入通道数 self.features = self.make_layers() # 自适应平局池化 在这里做了改进,摒弃了 大参数量的三层全连接层,改为自适应平均池化来替代 self.avgpool = nn.AdaptiveAvgPool1d(1)# # 定义全连接层 self.classifier = nn.Linear(conv_archs[-1][-1], num_classes) # CNN卷积池化结构构建 def make_layers(self): layers = [] for (num_convs, out_channels) in self.conv_arch: for _ in range(num_convs): layers.append(nn.Conv1d(self.input_channels, out_channels, kernel_size=3, padding=1)) layers.append(nn.ReLU(inplace=True)) self.input_channels = out_channels layers.append(nn.MaxPool1d(kernel_size=2, stride=2)) return nn.Sequential(*layers) #前向传播 def forward(self,input_seq): # torch.Size([32, 1024]) #改变输入形状,适应网络输入[batch,dim, seq_length] input_seq = input_seq.view(self.batch_size, 1, 1024) # 送入CNN网络模型 features = self.features(input_seq) # 调用,torch.Size([32, 128, 128]) # 自适应平均池化 x = self.avgpool(features) # ttorch.Size([32, 128, 1]) # 平铺 flat_tensor = x.view(self.batch_size, -1) # torch.Size([32, 128]) output = self.classifier(flat_tensor) # torch.Size([32, 10]) return output(1) 类定义和初始化 __init__batch_size:批次大小,表示每次训练时同时处理的数据样本数量。input_channels:输入数据的通道数。对于一维数据,通常为 1。conv_archs:CNN 网络结构的配置,是一个列表,其中每个元素是一个元组,指定了每个卷积块中卷积层的数量和输出通道数。num_classes:输出的维度,即分类任务中的类别数。self.batch_size:存储传入的参数batch_size,即每批次样本数量。self.conv_arch :存储传入的参数conv_archs,即每个卷积块中卷积层的数量和输出通道数。self.input_channels :存储传入的参数input_channels,即输入数据的通道数。self.features:通过调用 self.make_layers() 方法构建 CNN 的卷积和池化层。self.avgpool:定义一个自适应平均池化层,用于将特征图的空间维度压缩为1。self.classifier:定义一个全连接层,用于将特征映射到输出类别。(2) CNN 卷积池化结构构建 make_layers作用:根据 conv_archs 和 input_channels 构建 CNN 的卷积和池化层。遍历 conv_archs 中的每个元组,每个元组表示一个卷积块。对于每个卷积块,根据指定的卷积层数量和输出通道数,添加相应数量的卷积层 和 ReLU 激活层。在每个卷积块的末尾添加一个最大池化层,用于降低特征图的空间维度。返回值:将构建的层组合成一个 nn.Sequential 模块并返回。(3) 前向传播forward输入数据处理:将输入数据 input_seq 重塑为 [batch_size, 1, 1024] 的形状,以适应网络的输入要求。这里假设输入数据的长度为 1024,且只有一个特征通道。通过 CNN 层:将输入数据通过 self.features,提取特征,得到 features。输出形状为 [batch_size, 128, 128]。自适应平均池化:使用 self.avgpool 对特征图进行全局平均池化,输出形状为 [batch_size, 128, 1]。展平操作:将池化后的特征展平为 [batch_size, 128] 的形状。通过全连接层:将展平后的特征通过 self.classifier 全连接层进行分类,输出最终的分类结果,形状为 [batch_size, num_classes]。(4) 模型实例化#模型实例化batch_size = 32conv_archs = conv_archs = ((2, 32), (1, 64), (1, 128)) # vgg11input_channels = 1 # 做 1 D卷积, 输入维度为1num_classes = 10model = VGG1DModel(batch_size, input_channels, conv_archs, num_classes)batch_size = 32:批次大小为 32。conv_archs = ((2, 32), (1, 64), (1, 128)):CNN 网络结构配置,表示有三个卷积块,第一个卷积块包含两个卷积层,输出通道数为 32;第二个卷积块包含一个卷积层,输出通道数为 64;第三个卷积块包含一个卷积层,输出通道数为 128。input_channels = 1:输入通道数为 1,表示一维卷积。num_classes = 10:输出类别数为 10。(5) 打印模型观察框架print(model)#检查模型框架图1 1DCNN模型结构根据输出结果可以看出这个VGG1DModel是一个为一维数据设计的卷积神经网络模型,它由一系列卷积层、激活层、池化层以及最后的全连接层组成。模型的输入层接受单通道的一维数据,随后通过两个具有32个输出通道的卷积层,每个卷积层后面紧跟一个ReLU激活函数,用于增加非线性。接着是一个最大池化层,用于降低特征图的维度。然后,模型通过一个具有64个输出通道的卷积层,再次应用ReLU激活,随后是第二个最大池化层。接下来,模型通过一个具有128个输出通道的卷积层和第三个最大池化层,这之后是一个自适应平均池化层,将特征图的每个维度缩减到1。最后,一个全连接层将128个输入特征映射到10个输出类别,通常用于分类任务。整个网络结构旨在通过层层抽象提取一维数据的特征,并最终实现有效的分类。6.3.3模型训练# 训练模型import timeimport torch.nn.functional as Fimport matplotlibimport matplotlib.pyplot as pltmatplotlib.rc("font", family='Microsoft YaHei')def model_train(batch_size, epochs, train_loader, val_loader, model, optimizer, loss_function): model = model.to(device) # 定义损失函数和优化函数 loss_function = nn.CrossEntropyLoss(reduction='sum') # loss learn_rate = 0.0003 optimizer = torch.optim.Adam(model.parameters(), learn_rate) # 优化器 # 样本长度 train_size = len(train_loader) * batch_size val_size = len(val_loader) * batch_size # 最高准确率 最佳模型 best_accuracy = 0.0 best_model = model train_loss = [] # 记录在训练集上每个epoch的loss的变化情况 train_acc = [] # 记录在训练集上每个epoch的准确率的变化情况 validate_acc = [] validate_loss = [] # 计算模型运行时间 start_time = time.time() for epoch in range(epochs): # 训练 model.train() loss_epoch = 0. #保存当前epoch的loss和 correct_epoch = 0 #保存当前epoch的正确个数和 for seq, labels in train_loader: seq, labels = seq.to(device), labels.to(device) # print(seq.size(), labels.size()) torch.Size([32, 7, 1024]) torch.Size([32]) # 每次更新参数前都梯度归零和初始化 optimizer.zero_grad() # 前向传播 y_pred = model(seq) # torch.Size([16, 10]) # 对模型输出进行softmax操作,得到概率分布 probabilities = F.softmax(y_pred, dim=1) # 得到预测的类别(最大概率的标签) predicted_labels = torch.argmax(probabilities, dim=1) # 与真实标签进行比较,计算预测正确的样本数量 # 计算当前batch预测正确个数 correct_epoch += (predicted_labels == labels).sum().item() # 损失计算 loss = loss_function(y_pred, labels) loss_epoch += loss.item() # 反向传播和参数更新 loss.backward() optimizer.step() # break # break # 计算准确率 train_Accuracy = correct_epoch/train_size train_loss.append(loss_epoch/train_size) train_acc.append(train_Accuracy) print(f'Epoch: {epoch+1:2} train_Loss: {loss_epoch/train_size:10.8f} train_Accuracy:{train_Accuracy:4.4f}') # 每一个epoch结束后,在验证集上验证实验结果。 with torch.no_grad(): loss_validate = 0. correct_validate = 0 for data, label in val_loader: data, label = data.to(device), label.to(device) pre = model(data) # 对模型输出进行softmax操作,得到概率分布 probabilities = F.softmax(pre, dim=1) # 得到预测的类别 predicted_labels = torch.argmax(probabilities, dim=1) # 与真实标签进行比较,计算预测正确的样本数量 # 计算当前batch预测正确个数 correct_validate += (predicted_labels == label).sum().item() loss = loss_function(pre, label) loss_validate += loss.item() # print(f'validate_sum:{loss_validate}, validate_Acc:{correct_validate}') val_accuracy = correct_validate/val_size '' print(f'Epoch: {epoch+1:2} val_Loss:{loss_validate/val_size:10.8f}, validate_Acc:{val_accuracy:4.4f}') validate_loss.append(loss_validate/val_size) validate_acc.append(val_accuracy) # 如果当前模型的准确率优于之前的最佳准确率,则更新最佳模型 #保存当前最优模型参数 if val_accuracy > best_accuracy: best_accuracy = val_accuracy best_model = model# 更新最佳模型的参数 # 保存最后的参数 # torch.save(model, 'final_model_1dvgg.pt') # 保存最好的参数 torch.save(best_model, 'best_model_1dvgg.pt') print(f'\nDuration: {time.time() - start_time:.0f} seconds') # 保存结果 方便 后续画图处理 dump(train_loss, 'train_loss') dump(train_acc, 'train_acc') dump(validate_loss, 'validate_loss') dump(validate_acc, 'validate_acc') print("best_accuracy :", best_accuracy)# batch_size = 32epochs = 50# 模型训练model_train(batch_size, epochs, train_loader, val_loader, model, optimizer, loss_function)这段代码定义了一个 ’model_train‘的函数,用于训练一个深度学习模型。首先将模型移动到指定的设备上,计算训练集和验证集的样本总数,并初始化用于记录训练和验证过程中损失和准确率的列表以及存储最佳模型和最高准确率的变量。然后,在指定的训练轮数内,通过遍历训练数据加载器中的每个批次,进行前向传播、损失计算、反向传播和参数更新,同时记录每个 epoch 的训练损失和准确率。在每个 epoch 结束后,使用验证数据加载器评估模型性能,计算验证集的损失和准确率,并根据验证准确率更新最佳模型。最后,保存训练过程中最佳的模型参数到文件'best_model_1dvgg.pt'中,并计算模型训练的总运行时间。整个过程包含模型的训练、验证和性能评估等多个环节。图2 训练过程及结果(GPU版)根据代码结果可知,训练50次的情况下用时71s,其中验证集上最好的准确率是0.96,接着我们可以用曲线具体描述模型训练过程。import matplotlibimport matplotlib.pyplot as pltimport numpy as npfrom joblib import dump, loadmatplotlib.rc("font", family='Microsoft YaHei')# 加载数据train_loss = load('train_loss')train_acc = load('train_acc')validate_loss = load('validate_loss')validate_acc = load('validate_acc')# 创建训练损失图# 创建左侧图:损失plt.figure(figsize=(14, 7), dpi=300)plt.subplot(1, 2, 1)plt.plot(train_loss, label='Train-loss', marker='^', color='blue') # o ^ * s + x , marker='o'plt.plot(validate_loss, label='Validate-loss', marker='+', color='red') # 颜色 曲线类型 可灵活替换plt.xlabel('Epochs', fontsize=12)plt.ylabel('Loss', fontsize=12)plt.xticks(fontsize=10)plt.yticks(fontsize=10)plt.legend(fontsize=12)plt.title('training visualization : Training and Validation Loss', fontsize=16)# 创建右侧图:准确率plt.subplot(1, 2, 2)plt.plot(train_acc,color = 'orange', marker='o',label = 'Train-accuracy')plt.plot(validate_acc, color = 'green', marker='*',label = 'Validate_accuracy')plt.xlabel('Epochs', fontsize=12)plt.ylabel('Accuracy', fontsize=12)plt.xticks(fontsize=10)plt.yticks(fontsize=10)plt.legend(fontsize=12)plt.title(' training visualization : Training and Validation Accuracy', fontsize=16)plt.tight_layout() # 用于确保子图之间的距离适当plt.show()这段代码加载训练过程中的各个结果,其中train_loss代表训练集损失值、train_acc代表训练集准确率、validate_loss代表验证集损失值、validate_acc代表验证集准确率,并通过曲线图绘制训练过程,包含每次训练的准确率以及损失函数变化。图3 训练过程曲线结果如图所示,其中左图蓝色曲线是训练集损失函数变化,红色是验证集损失函数,右图中黄色是验证集准确率变化曲线,绿色是验证集准确率变化曲线。随着训练次数增加,损失函数逐渐减少,准确率逐渐增加趋近于1。6.3.4 模型验证模型验证部分代码首先用测试集输入最佳模型,并通过折线图以及准确率、召回率等指标检验模型效果,最后通过混淆矩阵进一步分析实验结果。# 模型 测试集 验证 from sklearn.metrics import confusion_matriximport torch.nn.functional as Fdevice = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 有GPU先用GPU训练print(device)# 得出每一类的分类准确率model = torch.load('best_model_1dvgg.pt')model = model.to(device)# 使用测试集数据进行推断并计算每一类的分类准确率true_labels = [] # 存储类别标签predicted_labels = [] # 存储预测的标签with torch.no_grad(): for test_data, test_label in test_loader: # 将模型设置为评估模式 model.eval() test_data = test_data.to(device) test_output = model(test_data) probabilities = F.softmax(test_output, dim=1) predicted = torch.argmax(probabilities, dim=1) true_labels.extend(test_label.tolist()) predicted_labels.extend(predicted.tolist())# 混淆矩阵confusion_mat = confusion_matrix(true_labels, predicted_labels)from sklearn.metrics import classification_report# 计算每一类的分类准确率report = classification_report(true_labels, predicted_labels, digits=4)print(report)首先,代码设置了一个设备变量 'device',用于确定模型将在 CPU 还是 GPU 上运行。如果系统中有可用的 CUDA(GPU)设备,'device'将被设置为 "cuda",否则将使用 "cpu"。然后,打印出当前选择的设备,以确认模型将在哪个设备上运行。接下来,代码加载了预训练的最佳模型参数文件 'best_model_1dvgg.pt',并将模型移动到之前设置的设备上。true_labels用于存储测试集的真实标签、predicted_labels用于存储测试集预测标签。然后,代码进入一个 'with torch.no_grad()' 块,这个上下文管理器用于禁用梯度计算,因为在推断过程中不需要计算梯度,这样可以减少内存消耗和加快计算速度。在该块内,代码遍历测试数据加载器'test_loader'中的每个批次数据 'test_data' 和对应的标签 'test_label'。对于每个批次的数据,将模型设置为评估模式 'model.eval()',这会关闭模型中的一些特定于训练的行为,如 'Dropout' 层。接着,将测试数据移动到指定的设备上,并进行前向传播 'est_output = model(test_data)',得到模型对测试数据的输出。然后,对模型输出进行 'softmax' 操作 'F.softmax(test_output, dim=1)',得到每个类别的概率分布。使用 'torch.argmax(probabilities, dim=1)'获取预测的类别标签,并将真实标签和预测标签分别添加到'true_labels'和 'predicted_labels'列表中。在完成所有测试数据的推断后,代码使用 'confusion_matrix`'函数计算混淆矩阵。混淆矩阵的行表示真实标签,列表示预测标签,矩阵中的每个元素表示对应类别对的样本数量。最后,代码使用 'classification_report'函数生成一个文本报告,显示主要的分类指标,包括精确率、召回率、F1 分数和支持度。'digits=4'参数表示结果保留四位小数。打印出分类报告,以查看每一类的分类准确率和其他指标,从而评估模型在测试集上的整体性能。图4 测试集文本报告根据生成文本报告,我们可以初步判断在调用训练得到的最佳模型对测试集检验时,标签0、标签1、标签3、标签7、标签9的F1得分达到了百分百,总体准确率为0.93。注:在机器学习和数据科学中,评价指标是用来衡量模型性能的标准。不同的问题类型(如分类、回归、聚类等)会使用不同的评价指标。以下是一些常见的评价指标:1) 分类问题的评价指标:准确率(Accuracy):正确预测的样本数占总样本数的比例。精确率(Precision):预测为正类的样本中实际为正类的比例。召回率(Recall):所有实际为正类的样本中,被正确预测为正类的比例。F1-score:精确率和召回率的调和平均数。AUC-ROC曲线:接收者操作特征曲线下的面积,用于衡量模型区分正负类的能力。混淆矩阵(Confusion Matrix):显示真实类别与预测类别之间的关系。 宏平均(Macro Average):这种方法计算每个类别的指标(如精确度、召回率、F1分数等),然后取这些指标的算术平均值。它对所有类别给予相同的权重,不考虑类别之间的样本数量差异。这意味着每个类别对最终的宏平均指标的贡献是相同的。 加权平均(Weighted Average):与宏平均不同,加权平均在计算指标时会考虑每个类别的样本数量。它为每个类别的指标赋予权重,这个权重通常是该类别样本数量占总样本数量的比例。因此,样本数量较多的类别对最终的加权平均指标的贡献更大 。2) 回归问题的评价指标:均方误差(Mean Squared Error, MSE):预测值与真实值差的平方的平均值。均方根误差(Root Mean Squared Error, RMSE):MSE的平方根。平均绝对误差(Mean Absolute Error, MAE):预测值与真实值差的绝对值的平均值例如,我们通过加载上述混淆矩阵并画出具体矩阵图分析模型效果。# 绘制混淆矩阵import matplotlib.pyplot as pltimport seaborn as sns# 原始标签和自定义标签的映射label_mapping = { 0: "C1",1: "C2",2: "C3",3: "C4",4: "C5", 5: "C6",6: "C7",7: "C8",8: "C9",9: "C10",}# 绘制混淆矩阵plt.figure(figsize=(10, 8), dpi=300)sns.heatmap(confusion_mat, xticklabels=label_mapping.values(), yticklabels=label_mapping.values(),annot=True, fmt='d', cmap='summer')plt.xlabel('Predicted Labels')plt.ylabel('True Labels')plt.title('Confusion Matrix')plt.show()图5 测试集混淆矩阵如图,混淆矩阵的行表示真实标签,列表示预测标签,矩阵中的每个元素表示对应类别对的样本数量。例如对标签2数据分析可知,标签2真实数据有48个,其中45个预测为标签2,有3个预测为标签8。在所有预测为标签2的数据中,有45个是正确的,其中1个标签5和4个标签8错误的预测为标签2。混淆矩阵那可以非常直观明了确定真实标签以及预测标签的分布情况。6.3.5 对比CPU版Pytorch图6 训练过程及结果(CPU版)通过对比可得,在简单的基础模型条件下,使用GPU计算可比CPU计算节省一半时间,在更复杂的数据及模型中GPU的运算速度及优势将更为明显。编辑:赵栓栓校核:李正平、陈凯歌、曹希铭、赵学功、白亮、王金、陈莹洁、陈宇航、任超、海洋、Tina、赵诚该文资料搜集自网络,仅用作学术分享,不做商业用途,若侵权,后台联系小编进行删除点击左下角阅读原文,即可在线阅读论文。 来源:故障诊断与python学习