机器学习之梯度消失和梯度爆炸

news2025/3/19 15:34:20

文章目录

    • 梯度消失
      • 1. 原理
      • 2. 影响
      • 3. 易出现情况
      • 4. 解决方法
      • 5. 编程实战案例
    • 梯度爆炸
      • 1. 原理
      • 2. 影响
      • 3. 易出现情况
      • 4. 解决方法
      • 5. 编程实战案例
    • 常用权重初始化方法及其影响
      • 1. 随机初始化
      • 2. Xavier初始化(Glorot初始化)
      • 3. Kaiming初始化(He初始化)
      • 4. Batch Normalization中的权重初始化
      • 5. 编程实战案例(以Xavier初始化和Kaiming初始化对比为例)

在深度学习的神经网络训练过程中,梯度消失和梯度爆炸是较为常见且会严重影响模型训练效果的问题。

梯度消失

1. 原理

在神经网络反向传播计算梯度时,某些激活函数(如sigmoid、tanh)具有特殊的特性。以sigmoid函数为例,其导数为 f ′ ( x ) = f ( x ) ( 1 − f ( x ) ) f'(x)=f(x)(1 - f(x)) f(x)=f(x)(1f(x)),当输入值 x x x处于较大或较小区间时, f ′ ( x ) f'(x) f(x)趋近于0。随着网络层数增多,梯度在反向传播经过多层时不断相乘,就如同多个小于1的数相乘,结果会越来越小,最终使得梯度趋近于0,导致前面的层难以更新参数。

2. 影响

由于前面层的参数几乎无法更新,训练过程会停滞不前,模型难以学习到数据的有效特征,进而致使模型拟合能力变差,无法准确进行预测和分类。

3. 易出现情况

  • 网络层数过深:层数的增加会使梯度传播经过更多层,激活函数导数的累积效应更加明显,梯度也就更容易趋近于0。
  • 激活函数选择不当:如果使用sigmoid、tanh等易导致梯度消失的激活函数,并且在网络中大量使用此类函数,那么梯度消失的问题会更加严重。
  • 权重初始化不合理:当权重初始化值过小时,在反向传播中,梯度与权重相乘后会不断衰减,从而引发梯度消失。
  • 数据特征分布差异大:特征分布的差异较大,会使得神经元的激活状态不同,部分数据可能使激活函数进入饱和区,导数变小,进而引发梯度消失。
  • 学习率设置过高:过高的学习率会使参数更新幅度过大,可能导致模型跳过最优解,表现出类似梯度消失的现象。

4. 解决方法

  • 更换激活函数:可以选用ReLU及其变体(如LeakyReLU、PReLU等)激活函数。这些激活函数在正数部分导数恒为1,能够有效避免梯度消失。
  • 采用合适的权重初始化方法:例如Xavier初始化,它会根据输入和输出神经元数量来初始化权重,使权重方差在正反向传播中保持一致,减少梯度问题。Kaiming初始化则适用于ReLU及其变体激活函数,能保证经过ReLU激活后的输出方差不变,稳定梯度。
  • 使用残差连接:通过跳跃连接让梯度能更直接地传播到前面的层,减少梯度消失的影响。
  • Batch Normalization:对数据进行归一化,减少内部协变量偏移,配合适当的权重初始化,提高模型的稳定性,减少梯度消失的发生。

5. 编程实战案例

通过构建两个深度神经网络,一个使用sigmoid激活函数,另一个使用ReLU激活函数,对比两者的损失曲线。代码如下:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

# 生成简单数据集
np.random.seed(0)
X = np.random.randn(100, 1)
y = 3 * X + 2 + 0.5 * np.random.randn(100, 1)
X = torch.FloatTensor(X)
y = torch.FloatTensor(y)

# 定义一个深度神经网络,使用sigmoid激活函数
class DeepNetwithSigmoid(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(DeepNetwithSigmoid, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        layers = []
        for i in range(num_layers):
            if i == 0:
                layers.append(nn.Linear(input_size, hidden_size))
            else:
                layers.append(nn.Linear(hidden_size, hidden_size))
            layers.append(nn.Sigmoid())
        layers.append(nn.Linear(hidden_size, 1))
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        return self.layers(x)

# 实例化模型、损失函数和优化器
input_size = 1
hidden_size = 10
num_layers = 10
model_sigmoid = DeepNetwithSigmoid(input_size, hidden_size, num_layers)
criterion = nn.MSELoss()
optimizer = optim.SGD(model_sigmoid.parameters(), lr=0.01)

# 训练模型
num_epochs = 500
losses_sigmoid = []
for epoch in range(num_epochs):
    optimizer.zero_grad()
    outputs = model_sigmoid(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()
    losses_sigmoid.append(loss.item())

# 定义一个使用ReLU激活函数的深度神经网络
class DeepNetwithReLU(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(DeepNetwithReLU, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        layers = []
        for i in range(num_layers):
            if i == 0:
                layers.append(nn.Linear(input_size, hidden_size))
            else:
                layers.append(nn.Linear(hidden_size, hidden_size))
            layers.append(nn.ReLU())
        layers.append(nn.Linear(hidden_size, 1))
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        return self.layers(x)

model_relu = DeepNetwithReLU(input_size, hidden_size, num_layers)
optimizer = optim.SGD(model_relu.parameters(), lr=0.01)
losses_relu = []
for epoch in range(num_epochs):
    optimizer.zero_grad()
    outputs = model_relu(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()
    losses_relu.append(loss.item())

# 绘制损失曲线
plt.plot(range(num_epochs), losses_sigmoid, label='Sigmoid Activation')
plt.plot(range(num_epochs), losses_relu, label='ReLU Activation')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()

运行代码后可以看到,使用sigmoid激活函数的网络由于梯度消失问题,损失下降缓慢,而使用ReLU激活函数的网络能有效避免梯度消失,损失下降较快。

梯度爆炸

1. 原理

在反向传播计算梯度时,由于网络层数过多、权重初始化过大或激活函数选择不当等原因,会使梯度值不断增大,呈指数级增长。例如,若权重矩阵过大,在反向传播中,梯度与权重不断相乘,就会导致梯度迅速增大。

2. 影响

模型参数更新幅度过大,训练过程不稳定,无法收敛,甚至模型输出结果异常,无法得到有效模型。

3. 易出现情况

  • 网络层数过深:层数增多时,如果权重等设置不当,梯度在传播中更容易被放大。
  • 激活函数选择不当:虽然不常见,但某些激活函数在特定情况下导数过大,也可能引发梯度爆炸。
  • 权重初始化不合理:权重初始化值过大,在反向传播中,梯度与权重相乘后会不断增大,从而引发梯度爆炸。
  • 数据特征分布差异大:异常大的特征值可能使梯度计算结果异常大,增加梯度爆炸的风险。
  • 学习率设置过高:过高的学习率使参数更新幅度过大,可能导致梯度不断放大,引发梯度爆炸。

4. 解决方法

  • 合理选择激活函数:避免使用易导致梯度爆炸的激活函数。
  • 合适的权重初始化:采用Xavier初始化、Kaiming初始化等方法,合理设置权重初始值。
  • 使用梯度截断技术:当梯度值超过一定阈值时,对梯度进行截断,使其保持在合理范围。
  • 优化网络结构:避免网络过于复杂,降低梯度传播出现问题的可能性。
  • Batch Normalization:通过归一化操作稳定数据分布,避免因输入数据变化过大引发梯度爆炸,同时限制权重更新幅度,降低梯度爆炸的可能性。

5. 编程实战案例

构建一个权重初始化较大的深度神经网络,容易引发梯度爆炸,通过对比不使用梯度截断和使用梯度截断两种情况下的训练过程,观察损失曲线的变化。代码如下:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

# 生成简单数据集
np.random.seed(0)
X = np.random.randn(100, 1)
y = 3 * X + 2 + 0.5 * np.random.randn(100, 1)
X = torch.FloatTensor(X)
y = torch.FloatTensor(y)

# 定义一个容易产生梯度爆炸的深度神经网络,权重初始化较大
class DeepNetwithLargeWeights(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(DeepNetwithLargeWeights, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        layers = []
        for i in range(num_layers):
            if i == 0:
                layer = nn.Linear(input_size, hidden_size)
                nn.init.normal_(layer.weight, mean=0, std=10)
                layers.append(layer)
            else:
                layer = nn.Linear(hidden_size, hidden_size)
                nn.init.normal_(layer.weight, mean=0, std=10)
                layers.append(layer)
            layers.append(nn.ReLU())
        layer = nn.Linear(hidden_size, 1)
        nn.init.normal_(layer.weight, mean=0, std=10)
        layers.append(layer)
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        return self.layers(x)

# 实例化模型、损失函数和优化器
input_size = 1
hidden_size = 10
num_layers = 10
model_large_weights = DeepNetwithLargeWeights(input_size, hidden_size, num_layers)
criterion = nn.MSELoss()
optimizer = optim.SGD(model_large_weights.parameters(), lr=0.1)

# 训练模型,不使用梯度截断
num_epochs = 50
losses_no_clip = []
for epoch in range(num_epochs):
    optimizer.zero_grad()
    outputs = model_large_weights(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()
    losses_no_clip.append(loss.item())

# 训练模型,使用梯度截断
model_large_weights_clip = DeepNetwithLargeWeights(input_size, hidden_size, num_layers)
optimizer = optim.SGD(model_large_weights_clip.parameters(), lr=0.1)
losses_with_clip = []
for epoch in range(num_epochs):
    optimizer.zero_grad()
    outputs = model_large_weights_clip(X)
    loss = criterion(outputs, y)
    loss.backward()
    torch.nn.utils.clip_grad_norm_(model_large_weights_clip.parameters(), max_norm=10)
    optimizer.step()
    losses_with_clip.append(loss.item())

# 绘制损失曲线
plt.plot(range(num_epochs), losses_no_clip, label='No Gradient Clipping')
plt.plot(range(num_epochs), losses_with_clip, label='Gradient Clipping')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()

从损失曲线可以看出,不使用梯度截断时,由于梯度爆炸,损失值迅速增大且不稳定;而使用梯度截断后,模型训练相对稳定,损失能够逐渐下降。

常用权重初始化方法及其影响

1. 随机初始化

  • 方法:从均匀分布或正态分布中随机采样初始化权重,例如从均匀分布 U ( − 6 / ( n i n + n o u t ) , 6 / ( n i n + n o u t ) ) U(-\sqrt{6/(n_{in}+n_{out})}, \sqrt{6/(n_{in}+n_{out})}) U(6/(nin+nout) ,6/(nin+nout) )中采样,其中 n i n n_{in} nin n o u t n_{out} nout分别为输入和输出神经元数量。
  • 影响:值过小容易引发梯度消失,过大则会增加梯度爆炸的风险。

2. Xavier初始化(Glorot初始化)

  • 方法:均匀分布时初始化范围是 U ( − 6 / ( n i n + n o u t ) , 6 / ( n i n + n o u t ) ) U(-\sqrt{6/(n_{in}+n_{out})}, \sqrt{6/(n_{in}+n_{out})}) U(6/(nin+nout) ,6/(nin+nout) ),正态分布时均值为0,方差为 2 / ( n i n + n o u t ) 2/(n_{in}+n_{out}) 2/(nin+nout)
  • 影响:使权重方差在正反向传播中保持一致,让梯度平稳传播,减少梯度问题,提升训练的稳定性和收敛速度。

3. Kaiming初始化(He初始化)

  • 方法:正态分布时均值为0,方差为 2 / n i n 2/n_{in} 2/nin;均匀分布时范围是 U ( − 6 / n i n , 6 / n i n ) U(-\sqrt{6/n_{in}}, \sqrt{6/n_{in}}) U(6/nin ,6/nin ) n i n n_{in} nin为输入神经元数量。
  • 影响:适用于ReLU及其变体激活函数,保证经过ReLU激活后的输出方差不变,稳定梯度,有效缓解梯度消失,在深层网络中效果显著。

4. Batch Normalization中的权重初始化

  • 方法:卷积层或全连接层后的权重常初始化为单位矩阵或接近单位矩阵,偏置项初始化为0。Batch Normalization层中,可学习参数 γ \gamma γ β \beta β通常初始化为1和0。
  • 影响:Batch Normalization减少内部协变量偏移,使网络对权重初始化不那么敏感,配合适当的权重初始化,进一步提高模型的稳定性,减少梯度消失和梯度爆炸的发生。

5. 编程实战案例(以Xavier初始化和Kaiming初始化对比为例)

通过构建分别使用Xavier初始化和Kaiming初始化的深度神经网络,对比两者的训练过程。代码如下:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

# 生成简单数据集
np.random.seed(0)
X = np.random.randn(100, 1)
y = 3 * X + 2 + 0.5 * np.random.randn(100, 1)
X = torch.FloatTensor(X)
y = torch.FloatTensor(y)

# 定义一个深度神经网络,使用Xavier初始化
class DeepNetwithXavier(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(DeepNetwithXavier, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        layers = []
        for i in range(num_layers):
            if i == 0:
                layer = nn.Linear(input_size, hidden_size)
                nn.init.xavier_uniform_(layer.weight)
                layers.append(layer)
            else:
                layer = nn.Linear(hidden_size, hidden_size)
                nn.init.xavier_uniform_(layer.weight)
                layers.append(layer)
            layers.append(nn.ReLU())
        layer = nn.Linear(hidden_size, 1)
        nn.init.xavier_uniform_(layer.weight)
        layers.append(layer)
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        return self.layers(x)

# 定义一个深度神经网络,使用Kaiming初始化
class DeepNetwithKaiming(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(DeepNetwithKaiming, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        layers = []
        for i in range(num_layers):
            if i == 0:
                layer = nn.Linear(input_size, hidden_size)
                nn.init.kaiming_uniform_(layer.weight)
                layers.append(layer)
            else:
                layer = nn.Linear(hidden_size, hidden_size)
                nn.init.kaiming_uniform_(layer.weight)
                layers.append(layer)
            layers.append(nn.ReLU())
        layer = nn.Linear(hidden_size, 1)
        nn.init.kaiming_uniform_(layer.weight)
        layers.append(layer)
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        return self.layers(x)

# 实例化模型、损失函数和优化器
input_size = 1
hidden_size = 10
num_layers = 10
model_xavier = DeepNetwithXavier(input_size, hidden_size, num_layers)
model_kaiming = DeepNetwithKaiming(input_size, hidden_size, num_layers)
criterion = nn.MSELoss()
optimizer_xavier = optim.SGD(model_xavier.parameters(), lr=0.01)
optimizer_kaiming = optim.SGD(model_kaiming.parameters(), lr=0.01)

# 训练使用Xavier初始化的模型
num_epochs = 500
losses_xavier = []
for epoch in range(num_epochs):
    optimizer_xavier.zero_grad()
    outputs = model_xavier(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer_xavier.step()
    losses_xavier.append(loss.item())

# 训练使用Kaiming初始化的模型
losses_kaiming = []
for epoch in range(num_epochs):
    optimizer_kaiming.zero_grad()
    outputs = model_kaiming(X)
    loss = criterion(outputs, y)
    loss.backward

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++基础 [五] - String的模拟实现

目录 前言 string类的模拟实现 成员函数的实现 构造函数 拷贝构造函数 赋值运算符重载 析构函数 元素访问的实现 operator[ ] Iterator - 迭代器 容量大小的实现 size capacity reserve ​编辑resize 内容修改的实现 push_back append operator(char ch) …

AIAgent有哪些不错的开源平台

AIAgent领域有许多优秀的开源平台和框架,以下是一些值得推荐的开源平台: AutoGPT AutoGPT 是一个基于 OpenAI 的 GPT-4 和 GPT-3.5 大型语言模型的开源框架,能够根据用户给定的目标自动生成所需提示,并利用多种工具 API 执行多步骤…

Python刷题:流程控制(上)

今天刷的是PythonTip的Python 入门挑战中的题,整体难度不高,适合小白练手以及巩固知识点。下面会进行详细讲解。 每日一句 每一个拼命努力的人,都像是独自穿越黑暗森林的行者, 没有并肩的身影,唯有孤独如影随形&…

vulhub/Billu_b0x靶机----练习攻略

1.Billu_b0x靶场下载链接: https://download.vulnhub.com/billu/Billu_b0x.zip 2.下载后,解压出ova文件,直接拖至VMware中,重命名和选择存储位置,点击导入,报错点击重试即可。修改网卡为NAT模式。 打开靶…

【YOLOv8】YOLOv8改进系列(8)----替换主干网络之Swin Transformer

主页:HABUO🍁主页:HABUO 🍁YOLOv8入门改进专栏🍁 🍁如果再也不能见到你,祝你早安,午安,晚安🍁 【YOLOv8改进系列】: 【YOLOv8】YOLOv8结构解读…

Qwen2-Audio:通义千问音频大模型技术解读

引言:从llm到mlm(audio) 大型语言模型(LLM)的发展日新月异,它们在文本理解、生成、推理等方面展现出惊人的能力。然而,交互模态不仅仅依赖于文字,语音、语调、环境音等听觉信息同样承载着丰富的内容。阿里巴巴通义千问团队,推出了 Qwen-Audio 系列模型,这里我们一起…

解决Java多张图合成JPG时出现红色前景及多列自适应适配

目录 前言 一、追本溯源 1、回到最开始 2、合成JPG的异常 二、解决问题 1、关于ImageType 2、TYPE_INT_RGB和TYPE_INT_ARGB 3、问题修复 4、列数自适应的问题 三、总结 前言 在当今数字化信息飞速发展的时代,图像处理技术在各个领域都占据着举足轻重的地位…

SpringBoot实现发邮件功能+邮件内容带模版

发送简单邮件模版邮件 1.pom引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><version>2.5.13</version></dependency><dependency><groupId&…

npm 报错 unable to resolve dependency tree

如下图&#xff1a; 解决&#xff1a;npm install --legacy-peer-deps 其实提示上有&#xff1a;npm ERR! Fix the upstream dependency conflict, or retry npm ERR! this command with --force, or --legacy-peer-deps

【蓝桥杯每日一题】3.17

&#x1f3dd;️专栏&#xff1a; 【蓝桥杯备篇】 &#x1f305;主页&#xff1a; f狐o狸x 他们说内存泄漏是bug&#xff0c;我说这是系统在逼我进化成SSR级程序员 OK来吧&#xff0c;不多废话&#xff0c;今天来点有难度的&#xff1a;二进制枚举 二进制枚举&#xff0c;就是…

Linux:冯诺依曼体系结构、操作系统、进程概念(一.初识进程)

文章目录 1.冯诺依曼体系结构总线与数据传输通路为什么有内存这个部分计算机存储结构 2.操作系统(Operator System)2.1 概念2.2 设计OS的目的2.3 理解“管理”先描述再组织 2.4 用户使用系统调用和库函数&#xff08;lib&#xff09;概念 总结 3.初识进程3.1 基本事实与引入3.2…

动手学深度学习:CNN和LeNet

前言 该篇文章记述从零如何实现CNN&#xff0c;以及LeNet对于之前数据集分类的提升效果。 从零实现卷积核 import torch def conv2d(X,k):h,wk.shapeYtorch.zeros((X.shape[0]-h1,X.shape[1]-w1))for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i,j](X[i:ih,j:jw…

删除排序链表中的重复元素(js实现,LeetCode:83)

看到这道题的第一反应是使用快慢指针&#xff0c;之前做过类似的题&#xff1a;删除有序数组中的重复项&#xff08;js实现&#xff0c;LeetCode&#xff1a;26&#xff09;原理都是一样,区别是这题需要将重复项删除&#xff0c;所以只需要走一遍单循环就可以实现 /*** Defini…

单片机自学总结

自从工作以来&#xff0c;一直努力耕耘单片机&#xff0c;至今&#xff0c;颇有收获。从51单片机&#xff0c;PIC单片机&#xff0c;直到STM32&#xff0c;以及RTOS和Linux&#xff0c;几乎天天在搞:51单片机&#xff0c;STM8S207单片机&#xff0c;PY32F003单片机&#xff0c;…

Unity教程(二十二)技能系统 分身技能

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

HTML5扫雷游戏开发实战

HTML5扫雷游戏开发实战 这里写目录标题 HTML5扫雷游戏开发实战项目介绍技术栈项目架构1. 游戏界面设计2. 核心类设计 核心功能实现1. 游戏初始化2. 地雷布置算法3. 数字计算逻辑4. 扫雷功能实现 性能优化1. DOM操作优化2. 算法优化 项目亮点技术难点突破1. 首次点击保护2. 连锁…

【Git学习笔记】Git分支管理策略及其结构原理分析

【Git学习笔记】Git分支管理策略及其结构原理分析 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;Git学习笔记 文章目录 【Git学习笔记】Git分支管理策略及其结构原理分析前言一.合并冲突二. 分支管理策略2.1 分支策略2.2 bug分支2.3 删除临…

Spring Cloud Alibaba Nacos 2023.X 配置问题

文章目录 问题现象&#xff08;一&#xff09;解决方法&#xff08;一&#xff09;问题现象&#xff08;二&#xff09;解决方法&#xff08;二&#xff09;问题现象&#xff08;三&#xff09;解决方法&#xff08;三&#xff09; 问题现象&#xff08;一&#xff09; Spring…

厨卫行业供应链产销协同前中后大平台现状需求分析报告+P120(120页PPT)(文末有下载方式)

资料解读&#xff1a;厨卫行业供应链产销协同前中后大平台现状需求分析报告 详细资料请看本解读文章的最后内容。在当前厨卫行业竞争激烈的市场环境下&#xff0c;企业的发展战略和业务模式创新至关重要。本次解读的报告围绕某厨卫企业展开&#xff0c;深入探讨其供应链产销协同…

我在哪,要去哪

在直播间听到一首好听的歌《我在哪&#xff0c;要去哪》-汤倩。 遇见的事&#xff1a;21~24号抽调去招生。 感受到的情绪&#xff1a;公假吗&#xff1f;给工作量吗&#xff1f;月工作量不够扣钱吗&#xff1f;报销方便吗&#xff1f;有事情&#xff0c;从来不解决后顾&#x…