【nlp】知识蒸馏Distilling

一、知识蒸馏介绍

1. 什么是知识蒸馏?

在这里插入图片描述
知识蒸馏(Knowledge Distillation) 是一种用于模型压缩的技术,通过让小模型(称为学生模型,student model)从大模型(称为教师模型,teacher model)中学习,从而提高小模型的性能,同时保留大模型的一部分知识。知识蒸馏常用于深度学习中,以减少计算资源和内存需求,使得模型可以在资源受限的设备上运行,比如移动设备和嵌入式系统。

2. 轻量化网络方式有哪些?

1. 压缩已训练好的模型

  • 知识蒸馏:将大模型的知识传递给小模型,通过模仿大模型的输出提高小模型的性能。
  • 权值量化:将浮点数表示的权重转换为低精度整数(如 INT8)表示,减少模型体积和计算量。
  • 权重剪枝:移除不重要的权重或神经元,减少参数量和计算开销。
  • 通道剪枝:剪掉卷积层的某些通道,降低卷积计算的复杂性。
  • 注意力迁移:通过让小模型学习大模型的注意力机制,使其更好地关注重要的特征。

2. 直接训练轻量化网络

  • SqueezeNet:使用较少的参数量进行等效卷积操作。
  • MobileNetv1/v2/v3:引入深度可分离卷积(depthwise separable convolution)和倒残差结构,显著减少计算量。
  • MnasNet:通过神经架构搜索(NAS)设计的轻量化网络。
  • ShuffleNet:通过通道洗牌来优化组卷积的性能。
  • Xception:一种极度优化的深度可分离卷积网络。
  • EfficientNet:通过复合缩放(compound scaling)策略优化网络深度、宽度和分辨率。
  • EfficientDet:专门针对目标检测任务的轻量化网络,基于 EfficientNet 设计。

3. 加速卷积运算

  • im2col + GEMM:通过将卷积运算转换为矩阵乘法(General Matrix Multiplication)来加速计算。
  • Winograd 算法:用于减少卷积计算中的乘法操作,提升速度。
  • 低秩分解:将卷积核进行分解,减少参数量和计算量。

4. 硬件部署

  • TensorRT:NVIDIA 的深度学习推理库,通过优化模型来加速推理。
  • Jetson:NVIDIA 的嵌入式 AI 计算平台,适合低功耗场景。
  • TensorFlow-Slim:TensorFlow 中的轻量化网络构建工具,用于快速构建轻量模型。
  • OpenVINO:Intel 的推理工具套件,专注于边缘设备上的高效推理。
  • FPGA 集成电路:通过定制的集成电路实现高效的并行化计算,加速推理。

这些技术方法组合使用,可以在保持模型性能的同时大幅减少计算资源和存储需求,适合资源受限的应用场景如移动设备和嵌入式系统。

3. 软标签 vs 硬标签

  • 硬标签(hard targets):通常是训练数据的真实标签,通常采用 one-hot 编码。例如,图片分类任务中,图片所属的正确类别的概率为 1,其他类别的概率为 0。

  • 软标签(soft targets):通过教师模型的输出概率分布得到的标签。与硬标签不同,软标签是一个概率分布,包含了教师模型在所有类别上的预测概率。即使是错误类别,教师模型也会分配一个非零的概率。这些概率可以反映类别之间的相似性。

例如,对于一张图片,教师模型可能给出以下预测分布:

类别 A:70%
类别 B:20%
类别 C:5%
类别 D:5%

这表示该图片最有可能属于类别 A,但类别 B 也有一定的可能性。这样的概率分布提供了比硬标签(如 100% 属于类别 A)更多的细粒度信息。

在这里插入图片描述

4. 蒸馏温度 T T T

知识蒸馏中的温度作用

在标准的分类任务中,模型输出的是每个类别的预测概率,这些概率通常通过 Softmax 函数计算得到。Softmax 函数的定义如下:

P ( y = i ) = exp ⁡ ( z i / T ) ∑ j exp ⁡ ( z j / T ) P(y=i) = \frac{\exp(z_i / T)}{\sum_j \exp(z_j / T)} P(y=i)=jexp(zj/T)exp(zi/T)

其中, z i z_i zi 是第 i i i 类的 logits(即模型输出的未归一化分数), T T T 是温度参数。当 T = 1 T=1 T=1 时,Softmax 函数表现为标准的形式。如果温度 T > 1 T > 1 T>1,Softmax 的输出将变得“更软”,即各类之间的概率分布更加均匀;如果 T < 1 T < 1 T<1,Softmax 输出将变得更加尖锐,接近 one-hot 分布。

在知识蒸馏过程中,使用较高的温度(通常 T > 1 T>1 T>1)可以使教师模型输出的概率分布变得更加平滑,突出各类别之间的相对差异,而不是仅仅关注最高的概率类别。学生模型可以从这种软标签中学习到更多关于各个类别之间关系的信息,而不仅仅是从硬标签中学到的正确类别。
在这里插入图片描述

举例说明

假设我们有一个图像分类任务,教师模型是一种复杂的深度卷积神经网络(例如 ResNet-50),而学生模型是一个较小的模型(例如一个简单的卷积神经网络)。在知识蒸馏过程中,我们用教师模型的输出作为指导,来帮助学生模型学习。

  1. 无温度调整的硬标签训练: 学生模型仅从每个输入样本的真实类别标签(即 one-hot 编码)中学习,这些标签并没有包含类别之间的相关性或其他信息。

  2. 知识蒸馏中的软标签: 使用知识蒸馏时,首先通过调整温度参数 T > 1 T>1 T>1,教师模型输出的类别分布会变得更平滑。例如,对于某个输入图像,教师模型可能预测类别 A 的概率是 0.9,类别 B 的概率是 0.05,类别 C 的概率是 0.03,类别 D 的概率是 0.02。在温度调整后(例如 T = 5 T=5 T=5),这个分布可能会变为类别 A 的概率是 0.4,类别 B 的概率是 0.3,类别 C 的概率是 0.2,类别 D 的概率是 0.1。这个平滑后的分布反映了不同类别之间的相似性。

  3. 学生模型学习: 学生模型从这个更平滑的概率分布中学习,不仅学到了类别 A 的重要性,还学习到了类别 B 和类别 C 与类别 A 的相关性。这样可以帮助学生模型更好地理解数据之间的模式,从而提高泛化性能。

温度选择

温度 T T T 的选择非常关键,它决定了知识蒸馏的效果。较高的温度使得概率分布更平滑(矮胖),能够传递更多的类别信息,但也可能导致过度平滑,使得学生模型难以捕捉有用的信息。通常需要通过实验来确定最适合的温度值。

二、知识蒸馏过程

1. 知识蒸馏的过程

在这里插入图片描述

1. 输入数据

设输入数据为 x x x,同时输入给教师模型和学生模型。

2. 教师模型输出(Teacher Model Output)

教师模型是一个较复杂的神经网络,其通过 softmax 函数生成软标签。softmax 函数使用温度参数 T T T 来控制输出概率的平滑度:

q i teacher = exp ⁡ ( z i teacher / T ) ∑ j exp ⁡ ( z j teacher / T ) q_i^{\text{teacher}} = \frac{\exp(z_i^{\text{teacher}} / T)}{\sum_j \exp(z_j^{\text{teacher}} / T)} qiteacher=jexp(zjteacher/T)exp(ziteacher/T)

其中:

  • q i teacher q_i^{\text{teacher}} qiteacher 是教师模型生成的类别 i i i 的概率。
  • z i teacher z_i^{\text{teacher}} ziteacher 是教师模型的第 i i i 类别的 logit 值。
  • T T T 是温度参数,当 T > 1 T > 1 T>1 时,输出概率分布更加平滑,有助于学生模型学习类别间的相似性。

3. 学生模型输出(Student Model Output)

学生模型是一个较小的模型,它通过学习教师模型的软标签和真实标签来提高性能。学生模型的输出也通过 softmax 函数生成。

软预测(Soft Predictions):

学生模型生成的软预测是通过与教师模型相同温度 T T T 的 softmax 函数计算的:

q i student = exp ⁡ ( z i student / T ) ∑ j exp ⁡ ( z j student / T ) q_i^{\text{student}} = \frac{\exp(z_i^{\text{student}} / T)}{\sum_j \exp(z_j^{\text{student}} / T)} qistudent=jexp(zjstudent/T)exp(zistudent/T)

硬预测(Hard Predictions):

学生模型还生成硬预测,即通过正常的 softmax(温度 T = 1 T = 1 T=1)生成的标准输出,用于匹配真实标签:

q i hard = exp ⁡ ( z i student ) ∑ j exp ⁡ ( z j student ) q_i^{\text{hard}} = \frac{\exp(z_i^{\text{student}})}{\sum_j \exp(z_j^{\text{student}})} qihard=jexp(zjstudent)exp(zistudent)

4. 损失函数

为了训练学生模型,我们引入两个损失函数:

4.1 蒸馏损失(Distillation Loss)

蒸馏损失用于衡量学生模型的软预测和教师模型的软标签之间的差异。它通过使用**Kullback-Leibler 散度(KL 散度)**来度量这两个概率分布之间的距离:

L distill = KL ( q teacher , q student ) = ∑ i q i teacher log ⁡ ( q i teacher q i student ) L_{\text{distill}} = \text{KL}(q^{\text{teacher}}, q^{\text{student}}) = \sum_i q_i^{\text{teacher}} \log\left(\frac{q_i^{\text{teacher}}}{q_i^{\text{student}}}\right) Ldistill=KL(qteacher,qstudent)=iqiteacherlog(qistudentqiteacher)

其中:

  • q teacher q^{\text{teacher}} qteacher 是教师模型生成的软标签。
  • q student q^{\text{student}} qstudent 是学生模型生成的软预测。
4.2 学生损失(Student Loss)

学生损失是学生模型的硬预测与真实标签(硬标签)之间的差异,通常使用交叉熵损失计算:

L student = − ∑ i y i log ⁡ ( q i hard ) L_{\text{student}} = - \sum_i y_i \log(q_i^{\text{hard}}) Lstudent=iyilog(qihard)

其中:

  • y i y_i yi 是真实标签的 one-hot 编码。
  • q i hard q_i^{\text{hard}} qihard 是学生模型对类别 i i i 的硬预测概率。

5. 总损失函数

最终的总损失函数是蒸馏损失学生损失的加权和:

L total = α L student + β L distill L_{\text{total}} = \alpha L_{\text{student}} + \beta L_{\text{distill}} Ltotal=αLstudent+βLdistill

其中:

  • α \alpha α β \beta β 是权重系数,控制学生损失和蒸馏损失的相对重要性。通常 α \alpha α 可以设置为 1, β \beta β 可以调整以控制蒸馏的影响。
  • 为了确保梯度的缩放一致性,蒸馏损失部分的梯度通常会乘以 T 2 T^2 T2,因为软标签的梯度会随温度 T T T 缩放。

6. 温度参数 T T T 的影响

温度参数 T T T 控制了 softmax 函数的平滑程度。较高的 T T T 会使教师模型的输出概率分布更加平滑,从而让学生模型能够学习到类别间的相对关系。这些信息可以帮助学生模型提高泛化能力。

  • T = 1 T = 1 T=1 时,softmax 输出接近 one-hot 编码,类别之间的相对信息较少。
  • T > 1 T > 1 T>1 时,类别之间的概率差异缩小,学生模型 可以从这些更平滑的概率中学习到更多的信息。

在这里插入图片描述

前边的两个图是训练过程,后边一个图是预测过程。

2. 知识蒸馏发展趋势

  1. 教学助长
  2. 助教、多个老师、多个同学
  3. 知识的表示(中间层)、数据集蒸馏、对比学习
  4. 多模态、知识图谱、预训练大模型的知识蒸馏

论文:
Attention Transfer
channel-wise knowledge distillation for dense prediction
contrastive representation Distillation
Distill BERT

3. 实现代码

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torchvision import datasets, transforms
from torch.utils.data import DataLoader


# 1. 定义教师模型(较大的模型)
class TeacherModel(nn.Module):
    def __init__(self):
        super(TeacherModel, self).__init__()
        self.fc1 = nn.Linear(28 * 28, 1200)
        self.fc2 = nn.Linear(1200, 1200)
        self.fc3 = nn.Linear(1200, 10)

    def forward(self, x):
        x = x.view(-1, 28 * 28)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


# 2. 定义学生模型(较小的模型)
class StudentModel(nn.Module):
    def __init__(self):
        super(StudentModel, self).__init__()
        self.fc1 = nn.Linear(28 * 28, 800)
        self.fc2 = nn.Linear(800, 800)
        self.fc3 = nn.Linear(800, 10)

    def forward(self, x):
        x = x.view(-1, 28 * 28)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


# 3. 定义蒸馏损失函数
def distillation_loss(student_outputs, teacher_outputs, labels, T, alpha):
    """
    :param student_outputs: 学生模型的输出
    :param teacher_outputs: 教师模型的输出
    :param labels: 真实标签
    :param T: 温度参数
    :param alpha: 学生损失与蒸馏损失的权重
    :return: 总损失
    """
    # 计算学生模型的硬标签损失(交叉熵损失)
    hard_loss = F.cross_entropy(student_outputs, labels)

    # 计算软标签损失(KL 散度)
    soft_student = F.log_softmax(student_outputs / T, dim=1)
    soft_teacher = F.softmax(teacher_outputs / T, dim=1)
    soft_loss = F.kl_div(soft_student, soft_teacher, reduction='batchmean') * (T * T)

    # 总损失 = α * 硬损失 + (1 - α) * 软损失
    return alpha * hard_loss + (1 - alpha) * soft_loss


# 4. 数据加载
transform = transforms.Compose([transforms.ToTensor()])
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)

test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)


# 5. 训练过程
def train_student(teacher_model, student_model, train_loader, optimizer, T, alpha, epochs=5):
    teacher_model.eval()  # 教师模型是预训练的,设置为 eval 模式
    student_model.train()  # 学生模型将要训练

    for epoch in range(epochs):
        total_loss = 0.0
        for images, labels in train_loader:
            # images, labels = images.cuda(), labels.cuda()
            # 教师模型预测
            with torch.no_grad():
                teacher_outputs = teacher_model(images)

            # 学生模型预测
            student_outputs = student_model(images)

            # 计算蒸馏损失
            loss = distillation_loss(student_outputs, teacher_outputs, labels, T, alpha)

            # 优化器更新
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            total_loss += loss.item()

        print(f"Epoch [{epoch + 1}/{epochs}], Loss: {total_loss / len(train_loader):.4f}")


# 6. 测试过程
def test_model(model, test_loader):
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            # images, labels = images.cuda(), labels.cuda()
            outputs = model(images)
            _, predicted = torch.max(outputs, 1) # 返回每行(每个样本)的最大值和对应的索引
            total += labels.size(0) #更新样本计数
            correct += (predicted == labels).sum().item() # 更新正确预测计数

    print(f'Test Accuracy: {100 * correct / total:.2f}%')


# 7. 实例化模型并启动训练
# teacher_model = TeacherModel().cuda()
# student_model = StudentModel().cuda()
teacher_model = TeacherModel()
student_model = StudentModel()

# 假设教师模型已经预训练过
# 这里可以加载预训练的教师模型权重
# torch.load('teacher_model.pth', teacher_model)

optimizer = optim.Adam(student_model.parameters(), lr=0.001)

# 设定温度 T 和 α 参数
T = 20  # 温度
alpha = 0.7  # 学生损失与蒸馏损失的权重

# 训练学生模型
train_student(teacher_model, student_model, train_loader, optimizer, T, alpha, epochs=5)

# 测试学生模型
test_model(student_model, test_loader)

# 保存学生模型权重
torch.save(student_model.state_dict(),'student_model.pth')
# 保存教师模型权重
torch.save(teacher_model.state_dict(), 'teacher_model.pth')


输出:

Epoch [1/5], Loss: 0.4672
Epoch [2/5], Loss: 0.3833
Epoch [3/5], Loss: 0.3671
Epoch [4/5], Loss: 0.3566
Epoch [5/5], Loss: 0.3509
Test Accuracy: 98.44%

Process finished with exit code 0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/894948.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无人机初识及应用概览

随着科技的飞速发展&#xff0c;无人机作为一种新兴技术产品&#xff0c;逐渐走进了我们的日常生活和学习中。以下是对该文内容的全面总结&#xff0c;旨在帮助读者更好地理解和认识无人机的基本概念、分类、应用领域、国产标杆品牌以及四旋翼无人机的具体组成。 一、无人机的概…

联邦学习实验复现—MNISIT IID实验 pytorch

联邦学习论文复现&#x1f680; 在精度的联邦学习的论文之后打算进一步开展写一个联邦学习的基础代码&#xff0c;用于开展之后的相关研究&#xff0c;首先就是复现一下论文中最基础也是最经典的MNIST IID(独立同分布划分) 数据集。然后由于这个联邦学习的论文是谷歌发的&#…

html基础小练习

需求&#xff1a;实现如上图网页 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>注册界面</title></head><body><div><form action""><table width"400"><t…

Java21虚拟线程:我的锁去哪儿了?

0 前言 最近的文章中&#xff0c;我们详细介绍了当我们迁移到 Java 21 并将代际 ZGC 作为默认垃圾收集器时&#xff0c;我们的工作负载是如何受益的。虚拟线程是我们在这次迁移中兴奋采用的另一个特性。 对虚拟线程新手&#xff0c;它们被描述为“轻量级线程&#xff0c;大大…

推荐10 个令人惊叹的 Python 自动化脚本!

/01/ 剪贴板管理器 你是否曾发现自己忙于处理多个文本片段&#xff0c;而忘记了自己复制了什么&#xff1f;有没有想过有一个工具可以记录你一天中复制的所有内容&#xff1f; 这个自动化脚本可以监控你复制的所有内容&#xff0c;将复制的每个文本无缝地存储在一个时尚的图形…

C++ 在项目中使用GDB

一&#xff1a;GDB 的 TUI 模式使用 GDB的 TUI &#xff08;Text User Interface&#xff09;模式提供了一种图形化的调试体验&#xff0c;允许在终端中同时显示源代码&#xff0c;寄存器和汇编代码等信息&#xff0c;下面是GDB TUI的基本操作和快捷键 1. 显示源代码窗口&…

【C++】类的默认成员函数:深入剖析与应用(上)

&#x1f600;在上一篇文章中我们初步了解了C的基础概念&#xff0c;现在我们进行对C类的默认成员函数进行更加深入的理解&#xff01; &#x1f449;【C新手入门指南&#xff1a;从基础概念到实践之路】 目录 &#x1f4af;前言 &#x1f4af;构造函数 一、构造函数的定义…

常见TCP/IP协议基础——计算机网络

目录 前言常见协议基础常见协议-基于TCP的应用层协议常见协议-基于UDP的应用层协议常见协议-网络层协议习题自测1.邮件发送协议2.接收邮件协议端口3.建立连接4.层次对应关系5.FTP服务器端口 前言 本笔记为备考软件设计师时的重点知识点笔记&#xff0c;关于常见TCP/IP协议基础…

【飞腾加固服务器】全国产化解决方案:飞腾FT2000+/64核,赋能关键任务保驾护航

在信息安全和自主可控的时代背景下&#xff0c;国产化设备的需求与日俱增&#xff0c;尤其是在国防、航空航天、能源和其他关键行业。高可靠性和极端环境设计的国产加固服务器&#xff0c;搭载强大的飞腾FT2000/64核处理器&#xff0c;全面满足国产自主可控的严苛要求。 性能强…

Python案例小练习——小计算器

文章目录 前言一、代码展示二、运行展示 前言 这是用python实现一个简单的计器。 一、代码展示 def calculate(num1, op, num2):if op "":return float(num1) float(num2)elif op "-":return float(num1) - float(num2)elif op "*":return…

stable diffusion安装ai绘画真人动漫win中文版软件

前言 所有的AI设计工具&#xff0c;安装包、模型和插件&#xff0c;都已经整理好了&#xff0c;&#x1f447;获取~ Stable Diffusion&#xff08;简称SD&#xff09;&#xff0c;是通过数学算法实现文本输入&#xff0c;图像输出的开源软件&#xff01; 引用维基百科&#x…

expect工具

一.expect工具介绍 在写脚本的过程当中不可避免的需要去写交互式命令 那么如何让交互式命令在脚本中自动执行&#xff1f; 使用expect工具 作用&#xff1a;捕获交互式的输出&#xff0c;自动执行交互式命令 如上图所示&#xff0c;可以使用expect工具去捕获交互式命令的提…

什么是大数据分析:定义、优缺点、应用、机遇和风险

大数据分析的概念已经成为我们社会不可或缺的一部分。众多公司和机构已经开发了大数据应用程序&#xff0c;取得了不同程度的成功。社交媒体平台和传感器等技术正在以前所未有的速度生成数据&#xff0c;就像一条装配线。如今&#xff0c;几乎所有东西都是物联网的一部分&#…

[Xshell] Xshell的下载安装使用及连接linux过程 详解(附下载链接)

前言 Xshell.zip 链接&#xff1a;https://pan.quark.cn/s/5d9d1836fafc 提取码&#xff1a;SPn7 安装 下载后解压得到文件 安装路径不要有中文 打开文件 注意&#xff01;360等软件会拦截创建注册表的行为&#xff0c;需要全部允许、同意。或者退出360以后再安装。 在“绿化…

vscode pylance怎么识别通过sys.path.append引入的库

问题 假如我有一个Python项目 - root_path -- moduleA ---- fileA.py -- moduleB ---- fileB.py# fileAimport sys sys.path.append(moduleB)import fileB # vscode pylance找不到&#xff0c;因为sys.path.append(moduleB)是动态添加的print(fileB)结果 代码正常运行但是vs…

【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第五十四章 Pinctrl 子系统和 GPIO 子系统

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

基于百度智能体开发爱情三十六计

基于百度智能体开发爱情三十六计 文章目录 基于百度智能体开发爱情三十六计1. 爱情三十六计智能体2. 三十六计开发创意3. 智能体开发实践3.1 基础配置3.2 进阶配置3.3 调优心得3.4可能会遇到的问题 4. 为什么选择文心智能体平台 1. 爱情三十六计智能体 爱情三十六计 是一款基于…

Kaggle竞赛——森林覆盖类型分类

目录 1. 竞赛简要2. 数据分析2.1 特征类型统计2.2 四个荒野区域数据分析2.3 连续特征分析2.4 离散特征分析2.5 特征相关性热图2.6 特征间的散点关系图 3. 特征工程3.1 特征组合3.2 连续特征标准化 4. 模型搭建4.1 模型定义4.2 绘制混淆矩阵和ROC曲线4.3 模型对比与选择 5. 测试…

从0-1实战演练后台管理系统 (3)还在寻找优秀的后台管理系统?Pure Admin 源码及目录结构带你一探究竟!

一、获取源码: 从-gitee-上拉取从 Gitee 上拉取 1、完整版前端代码 git clone https://gitee.com/yiming_chang/vue-pure-admin.git2、国际化精简版前端代码 git clone -b i18n https://gitee.com/yiming_chang/pure-admin-thin.git3、非国际化精简版前端代码 git clone ht…

【Vue】Vue扫盲(七)如何使用Vue脚手架进行模块化开发及遇到的问题(cmd中无法识别vue命令、vue init webpack 命令执行失败)

上篇文章&#xff1a; Vue】Vue扫盲&#xff08;六&#xff09;关于 Vue 项目运行以及文件关系和关联的详细介绍 文章目录 一、安装 相关工具二、处理相关问题问题一&#xff1a;vue -v 提示 vue不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。问题二&#xf…