从认识AI开始-----生成对抗网络(GAN):通过博弈机制,引导生成

前言

生成对抗网络(GAN)是lan J. Goodfellow团队在2014年提出的生成架构, 该架构自诞生起,就产生了很多的话题,更是被称为生成对抗网络是“新世纪以来机器学习领域内最有趣的想法”。如今,基于生成对抗网络思想的架构在图像处理、生成方面的能力越来越强大,已经成为视觉领域中不可忽视的存在,可以这样说,GAN的诞生,让这个世界的物理表象变得具有欺骗性了


一、GAN的原理

最初GAN的目标就是用来生成图像,首先GAN的目标就是利用生成器 G 根据真实数据生成的假数据,并希望生成的假数据能够以假乱真,从而骗过判别器 D;同时,又希望判别器 D 能够区分真假数据。如下所示:

整个网络由生成器 G 和判别器 D 构成,随机初始化噪声数据,然后输入生成器生成假数据,判别器判断生成的数据和真实数据哪个才是真的。生成器没有标签,是无监督网络,判别器是监督网络,标签是“真或假”(0/1)。原始论文规定判别器输出当前数据为真的概率(标签为1的概率),当概率大于0.5,判别器认为样本是真实数据,小于0.5,判别器认为样本是由生成器生成的假数据。

其核心思想就是:

  • 通过两个神经网络(生成器 G 与判别器 D)之间的对抗博弈,让生成器学会产生以假乱真的数据

二、GAN的损失函数

其实GAN的整过训练过程就是一个零和博弈。在训练过程中,生成器和判别器的目标是相互竞争的:生成器的任务是尽可能生成以假乱真的数据,让判别器判断不出来,其目的就是让判别器的准确性降低;箱单,判别器的目的是尽量判断出真伪,让自己判断的准确性越来越高。

当生成器生成的数据越来越真时,判别器为保证自己的准确性,就会朝着判断能力强的方向迭代。当判断器判断能力越来越强大时,生成器为了保证自己生成的真实性,就会朝着生成能力强的方向迭代。在整个的关系中,判别器的准确性由论文中定义的交叉熵 V 来衡量,判别器和生成器共同影响着 V

1. 交叉熵 V

在生成器和判别器的特殊关系中,GAN的目标损失 V 为:

\min\limits_{G}\max\limits_{D}V(D,G)=\mathbb{E}_{x\sim p_{data}}\left[\log D(x_) \right ]+\mathbb{E}_{z\sim p_z}\left[\log (1-D(G(z))) \right ]

由于期望代表的是数据均值,因此,式子可以改为:

\begin{aligned} \min\limits_{G}\max\limits_{D}V(D,G) &=\frac {1}{n}\sum_{i=1}^{n}\log D(x_i)+\frac {1}{n}\sum_{i=1}^{n}\log (1-D(G(z_i))) \\ &= \frac {1}{n}\sum_{i=1}^{n}\left [ \log D(x_i)+\log (1-D(G(z_i))) \right ] \end{aligned}

 其中,x_i 为真实数据,z_i 为与真实数据结构相似的随机噪音,G(z_i) 为生成器生成的假数据,D(x_i) 为判别器在真实数据 x_i 上的判别的结果,D(G(z_i)) 为判别器在假数据(G(z_i))上判别的结果,其中 D(x_i) 与 D(G(z_i)) 都是样本为真(标签为1)的概率。

由于 D(x_i) 与 D(G(z_i)) 都是概率,所以值在 (0,1] 之间,因此,取对数后的值域为(-\propto ,0),所以损失 V 的值域也在(-\propto ,0)。并且 V 在判别器的能力最好时达到最大值,说明判别器越准确,V反而越大,这显然与普通的二分类损失相反。但是,如果分别从判别器和生成器的角度看,又是合理的。

2. 对于判别器损失

在 V 的表达式中,对数都与判别器有关,因此,对于判别器来说,V 即判别器的损失:

\min\limits_{G}\max\limits_{D}V(D,G)=\frac {1}{n}\sum_{i=1}^{n}\left [ \log D(x_i)+\log (1-D(G(z_i))) \right ]

我解释一下,判别器的目的是尽量使自己作出正确的判断,且判别器输出的是标签为真的概率,因此,判别器的最佳表现是:对于所有在真实数据上的判别器的输出 D(x_i) 都接近1,所有假数据上判别器 D(G(z_i)) 都接近0,因此,对于判别器的最佳损失就是:

\begin{aligned} \max\limits_{D}L_D &= \frac {1}{n} \sum _{i=1}^{n}\left [ \log D(x_i)+\log (1-D(G(z_i)) \right ] \\ &=\frac {1}{n} \sum _{i=1}^{n}\left [ \log 1+\log (1-0) \right ] \\ &=0 \end{aligned}

  • 因此,判别器希望 L_D 越大越好,即\max\limits_{D},判别能力越强,值越大,理想情况下值最大为0。

3. 对于生成器损失

V 的表达式中,生成器只会影响 D(G(z_i)),因此只有 V 的后半部分的表达式与生成器有关,即:

\min\limits_{G}L_G=\frac {1}{n} \sum _{i=1}^{n}\left[C+\log (1-D(G(z_i))) \right ]

去掉常数项:

\min\limits_{G}L_G=\frac {1}{n} \sum _{i=1}^{n}\log (1-D(G(z_i)))

生成器的目标是尽可能使生成的假数据让判别器判断为真,即 D(G(z_i)) 越接近1越好,因此,对于生成器的最佳损失为:

\min\limits_{G}L_G=\frac {1}{n} \sum _{i=1}^{n}\log (1-1))=-\propto

  • 可以看出,生成器希望 L_G 越小越好,即\min\limits_{G}无限接近负无穷,因此生成器的本质就是追求D(G(z_i)) 无限接近 1。对生成器而言,V 更像是一个损失,即模型表现越好,该指标的值越低。
  • 从整个GAN的角度看,我们的目标就是与生成器的目标一致,因此,对于我们而言,V就被当做损失,并且越低越好。

4. 求最优解

上面我已经推导了GAN损失函数 V 的由来,那么如何求最优解呢?下面我们来推导一下:

\min\limits_{G}\max\limits_{D}V(D,G)=\mathbb{E}_{x\sim p_{data}}\left[\log D(x_) \right ]+\mathbb{E}_{z\sim p_z}\left[\log (1-D(G(z))) \right ]

第一步:固定生成器 G,求最优判别器 D:

当我们固定 G 时,要求最优判别器 D,此时 G 是确定的,因此 G(z) 生成了一个伪样本 x,这意味这我们可以把:

x=G(z)x 服从分布p_g(x),即x\sim p_g(x)

因此,第二项期望就可以写作:

\mathbb{E}_{z\sim p_z(z)}\left[\log (1-D(G(x))) \right ]=\mathbb{E}_{x\sim p_g(x)}\left[\log(1-D(x)) \right ]

所以,原式就变为了:

\min\limits_{G}\max\limits_{D}V(D,G)=\mathbb{E}_{x\sim p_{data}}\left[\log D(x_) \right ]+\mathbb{E}_{x\sim p_g(x)}\left[\log(1-D(x)) \right ]

我们将期望转化为积分:

V(D,G)=\int _x p_{data}(x)\log D(x)dx+\int _xp_{g}\log(1-D(x))dx

将两个分布 p_{data} 和 p_{g} 放在同一个积分中:

V(D,G)=\int _x \left[ p_{data}(x)\log D(x)+p_{g}(x)\log(1-D(x)) \right ]dx

这是一个关于 D(x) 的泛化优化问题,对每个点 x,我们要最大化,令:

f(D(x))=p_{data}(x)\log D(x)+p_{g}\log(1-D(x))

对 D(x) 求导数,令导数为 0,得到最优 D(x)

\frac {df}{dD}=\frac {p_{data}(x)}{D(x)}- \frac {p_g(x)}{1-D(x)}=0

解得:

\frac {p_{data}(x)}{D(x)}=\frac {p_g(x)}{1-D(x)}

D(x)=\frac {p_{data}(x)}{p_{data}(x)+p_g(x)}

第二步:将 D(x) 代入原损失函数,优化生成器的目标  \min\limits_{G} \max\limits_{D}V(D,G)

\begin{aligned} V(D,G) =\int _xp_{data}(x)log(\frac {p_{data}(x)}{p_{data}(x)+p_g(x)})dx+\int _x p_g(x)log(\frac {p_{g}(x)}{p_{data}(x)+p_g(x)})dx \end{aligned}

我们对其化简:

\begin{aligned} V(D,G) &=\int _xp_{data}(x)log(\frac {p_{data}(x)}{\frac {p_{data}(x)+p_g(x)}{2}}\frac {1}{2})dx+\int _x p_{x}\log (\frac {p_g(x)}{\frac {p_g(x)+p_{data}(x)}{2}}\frac {1}{2})dx \\ &= \int _xp_{data}(x)log(\frac {p_{data}(x)}{\frac {p_{data}(x)+p_g(x)}{2}})dx+\int _x p_{x}\log (\frac {p_g(x)}{\frac {p_g(x)+p_{data}(x)}{2}})dx +\int _x \log \frac {1}{2} p_{data}(x)dx+\int _x \log \frac {1}{2} p_g(x)dx \\ &= \int _xp_{data}(x)log(\frac {p_{data}(x)}{\frac {p_{data}(x)+p_g(x)}{2}})dx+\int _x p_{x}\log (\frac {p_g(x)}{\frac {p_g(x)+p_{data}(x)}{2}})dx +\log \frac {1}{2}\int _x p_{data}(x)dx+\log \frac {1}{2}\int _x p_g(x)dx \\ &= \int _xp_{data}(x)log(\frac {p_{data}(x)}{\frac {p_{data}(x)+p_g(x)}{2}})dx+\int _x p_{x}\log (\frac {p_g(x)}{\frac {p_g(x)+p_{data}(x)}{2}})dx +\log \frac {1}{2}+\log \frac {1}{2} \\ &= \int _xp_{data}(x)log(\frac {p_{data}(x)}{\frac {p_{data}(x)+p_g(x)}{2}})dx+\int _x p_{x}\log (\frac {p_g(x)}{\frac {p_g(x)+p_{data}(x)}{2}})dx +\log \frac {1}{4} \\ &= KL\left ( p_{data}(x)||\frac {p_{data}(x)+p_g(x)}{2} \right )+KL\left ( p_g(x)||\frac {p_{data}(x)+p_g(x)}{2} \right )-\log 4 \end{aligned}

这里,我们介绍一个概念,Jensen-Shannon散度,是衡量两个分布差异的对称度量,它与KL散度有如下关系:

\begin{aligned} JS(p_{a}(x)||p_{b}(x))=\frac {1}{2}KL(p_{a}(x)||m)+\frac {1}{2}KL(p_{b}(x)||m) \end{aligned}

因此,最终式子变为:

\begin{aligned} V(D,G) &= 2*JS(p_{data}{x}||p_{g)(x)})-\log \frac {1}{4} \end{aligned}

若要使得 V(D,G) 取得最小,那么KL散度应当为0,当KL散度为0时,就相当于:

\begin{aligned} p_{data}(x) &=\frac {p_{data}(x)+p_g(x)}{2} \\ p_{data}(x) &=p_g(x) \end{aligned})

由此可知, p_{g}(x) 逼近p_{data}(x) 时,目标函数取得最优值,并且当

\begin{aligned} D(x) &=\frac {p_{data}(x)}{p_g(x)+p_{data}(x)} \\ &=\frac {1}{2} \end{aligned}

判别器就无法判断出样本是来自假数据样本 p_{g}(x),还是来自真实数据样本p_{data}(x) 了,此时生成器的生成效果便达到了最好。


三、GAN的训练流程

接下来,我将使用MINST数据集来实现一下GAN的训练流程:

训练过程:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torchvision.utils import save_image, make_grid
from torch.utils.tensorboard import SummaryWriter
import os# 定义生成器与判别器
class Generator(nn.Module):def __init__(self, latent_dim):super().__init__()self.net = nn.Sequential(nn.ConvTranspose2d(latent_dim, 256, 4, 1, 0),  # 1x1 -> 4x4nn.BatchNorm2d(256),nn.ReLU(True),nn.ConvTranspose2d(256, 128, 4, 2, 1),  # 4x4 -> 8x8nn.BatchNorm2d(128),nn.ReLU(True),nn.ConvTranspose2d(128, 64, 4, 2, 1),   # 8x8 -> 16x16nn.BatchNorm2d(64),nn.ReLU(True),nn.ConvTranspose2d(64, 1, 4, 4, 0),     # 16x16 -> 64x64nn.Tanh())def forward(self, z):return self.net(z)class Discriminator(nn.Module):def __init__(self):super().__init__()self.net = nn.Sequential(nn.Conv2d(1, 64, 4, 4, 0),  # 64x64 -> 16x16nn.LeakyReLU(0.2, inplace=True),nn.Conv2d(64, 128, 4, 2, 1),  # 16x16 -> 8x8nn.BatchNorm2d(128),nn.LeakyReLU(0.2, inplace=True),nn.Conv2d(128, 256, 4, 2, 1),  # 8x8 -> 4x4nn.BatchNorm2d(256),nn.LeakyReLU(0.2, inplace=True),nn.Conv2d(256, 1, 4, 1, 0),   # 4x4 -> 1x1nn.Sigmoid())def forward(self, x):return self.net(x).view(-1, 1).squeeze(1)
# 设置超参数
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
latent_dim = 100
batch_size = 128
epochs = 50
image_size = 64
lr = 2e-4
log_dir = "./GAN/runs/log"
sample_dir = "./GAN/samples"
os.makedirs(sample_dir, exist_ok=True)# 加载数据
transform = transforms.Compose([transforms.Resize(image_size),transforms.ToTensor(),transforms.Normalize([0.5], [0.5])
])
dataset = datasets.MNIST(root='./GAN', train=True, transform=transform, download=False)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)G = Generator(latent_dim).to(device)
D = Discriminator().to(device)
criterion = nn.BCELoss()
optimizer_G = optim.Adam(G.parameters(), lr=lr, betas=(0.5, 0.999))
optimizer_D = optim.Adam(D.parameters(), lr=lr, betas=(0.5, 0.999))writer = SummaryWriter(log_dir)
fixed_noise = torch.randn(64, latent_dim, 1, 1, device=device)
best_d_loss = float('inf')
# 训练
for epoch in range(epochs):for i, (real_imgs, _) in enumerate(dataloader):real_imgs = real_imgs.to(device)valid = torch.ones(real_imgs.size(0), device=device)fake = torch.zeros(real_imgs.size(0), device=device)# -------------------#  训练生成器 G# -------------------optimizer_G.zero_grad()z = torch.randn(real_imgs.size(0), latent_dim, 1, 1, device=device)gen_imgs = G(z)g_loss = criterion(D(gen_imgs), valid)g_loss.backward()optimizer_G.step()# -----------------------#  训练判别器 D# -----------------------optimizer_D.zero_grad()real_loss = criterion(D(real_imgs), valid)fake_loss = criterion(D(gen_imgs.detach()), fake)d_loss = real_loss + fake_lossd_loss.backward()optimizer_D.step()# 日志记录batches_done = epoch * len(dataloader) + iwriter.add_scalar("Loss/Generator", g_loss.item(), batches_done)writer.add_scalar("Loss/Discriminator", d_loss.item(), batches_done)print(f"Epoch {epoch+1}/{epochs} | G_loss: {g_loss.item():.4f} | D_loss: {d_loss.item():.4f}")# 保存最优模型if d_loss.item() < best_d_loss:best_d_loss = d_loss.item()torch.save(G.state_dict(), "best_generator.pth")torch.save(D.state_dict(), "best_discriminator.pth")

生成:

# 生成新图像
加载保存训练好的生成器
G.load_state_dict(torch.load("best_generator.pth", map_location=device))
G.eval()
noise = torch.randn(64, latent_dim, 1, 1, device=device)
with torch.no_grad():fake_imgs = G(noise).detach().cpu()
os.makedirs("final_samples", exist_ok=True)
grid = make_grid(fake_imgs, nrow=8, normalize=True)
save_image(grid, "final_samples/generated_grid.png")

在这里,我简单的训练了一个GAN网络,并生成64张数字图片,生成效果如下:

可以看到,简单训练的GAN能够生成不错的效果。


总结

 以上就是本文对GAN原理的全部介绍,相信小伙伴们在看完之后对GAN的原理会有更深刻的理解。总的来说,GAN为我们带来了新的视角,它让我们不再试图去拟合复杂的数据分布,而是建立一个“博弈系统”,通过竞争机制驱动模型学习。从14年到现在,基于GAN架构的生成模型已经发展了很多,比如StyleGAN、CycleGAN等模型,但是它们的核心仍然是GAN的架构。


如果小伙伴们觉得本文对各位有帮助,欢迎:👍点赞 | ⭐ 收藏 |  🔔 关注。我将持续在专栏《人工智能》中更新人工智能知识,帮助各位小伙伴们打好扎实的理论与操作基础,欢迎🔔订阅本专栏,向AI工程师进阶!

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

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

相关文章

限流算法java实现

参考教程&#xff1a;2小时吃透4种分布式限流算法 1.计数器限流 public class CounterLimiter {// 开始时间private static long startTime System.currentTimeMillis();// 时间间隔&#xff0c;单位为msprivate long interval 1000L;// 限制访问次数private int limitCount…

Maven 构建性能优化深度剖析:原理、策略与实践

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

JS手写代码篇---手写深拷贝

17、深拷贝 深拷贝与浅拷贝最大的不同就是对象的属性是嵌套对象&#xff0c;会新建一个对象 步骤&#xff1a; 判断是否为对象判断是否为i数组或者对象&#xff0c;给新的有个容器遍历循环&#xff0c;如果是对象要遍历循环&#xff0c;采用递归 function deepCopy(obj){// …

【react实战】如何实现监听窗口大小变化

在日常开发场景中&#xff0c;监听窗口变化是一个比较常见又很重要的业务功能&#xff0c;其实实现起来也很简单&#xff0c;今天就来记录一下具体的实现以及注意事项。 实现思路 在 React 中&#xff0c;可以通过监听 window 的 resize 事件来检测可视区域&#xff08;viewp…

AVCap视频处理成帧和音频脚本

###############处理原视频&#xff0c;使其格式和原数据一样 import os import cv2 import subprocess import json from PIL import Image from pydub import AudioSegmentimport sys import shutil # &#x1f539; 第一步&#xff1a;强制检测并设置FFmpeg路径 &#x1f5…

数据冗余对企业运营的隐性成本

从客户管理到供应链优化&#xff0c;再到市场分析&#xff0c;数据无处不在&#xff0c;数据已成为企业运营的核心驱动力。然而&#xff0c;随着企业IT系统的多样化和数据量的激增&#xff0c;数据冗余&#xff08;Data Redundancy&#xff09;问题逐渐浮出水面&#xff0c;成为…

HTML原生日期插件增加周次显示

<div id="app" class="box box-info" style="border-top-color:white;"><!-- // 日期部分 --><div class="date-picker-container" style="position: relative; max-width: 200px;"><!-- 日期输入框 -…

渗透测试PortSwigger Labs:遭遇html编码和转义符的反射型XSS

1 处是我们输入的标签被服务器 html 编码后返回&#xff0c;被浏览器当作字符串显示出来&#xff0c;无法执行 javascript 2 处是唯一能控制的地方&#xff0c;正好在script标签范围内&#xff0c;可以尝试构造 依然存在转移单引号&#xff0c;我们输入转义符\让服务器添加的转…

Ansible 错误处理:确保高效自动化

当 Ansible 收到命令的非零返回码或模块故障时,默认情况下,它会停止在该主机上的执行,并在其他主机上继续执行。但是,在某些情况下,您可能需要不同的行为。有时非零返回码表示成功。有时您希望一台主机上的故障导致所有主机上的执行停止。Ansible 提供了处理这些情况的工具…

【无标题】NP完全问题的拓扑对偶统一解法 ——四色问题到P=NP的普适框架

NP完全问题的拓扑对偶统一解法 ——四色问题到PNP的普适框架 **摘要** 本文提出基于**拓扑膨胀-收缩对偶性**的计算理论框架&#xff0c;突破传统NP完全性理论局限。通过将离散组合问题转化为连续几何问题&#xff0c;并引入规范场量子求解机制&#xff0c;实现四色问题、子…

【Zephyr 系列 19】打造 BLE 模块完整 SDK:AT 命令系统 + 状态机 + NVS + OTA 一体化构建

🧠关键词:Zephyr、BLE 模块、SDK 构建、AT 命令框架、有限状态机、Flash 配置、MCUboot OTA 📌面向读者:希望将 BLE 项目标准化、封装化、支持量产使用的开发团队与架构师 📊预计字数:5500+ 字 🧭 背景与目标 在完成多个 BLE 功能模块后,一个企业级产品往往需要:…

机器学习核心概念速览

机器学习基本概念 有监督学习分类、回归无监督学习聚类、降维 一维数组 import numpy as np data np.array([1,2,3,4,5]) print(data) print(data.shape) print(len(data.shape))[1 2 3 4 5] (5,) 1二维数组 data2 np.array([[1,2,3],[4,5,6]]) print(data2) print(data2…

在 Java 中实现一个标准 Service 接口,并通过配置动态选择具体实现类供 Controller 调用

在 Java 中实现一个标准 Service 接口&#xff0c;并通过配置动态选择具体实现类供 Controller 调用&#xff0c;是解耦和灵活扩展的常见设计模式。 需求分析 当你需要开发一个需要灵活切换业务实现的系统&#xff0c;比如不同环境使用不同策略&#xff08;如测试环境用Mock实…

input+disabled/readonly问题

背景&#xff1a; vue2elementui <el-input v-model"inputForm.projectName" class"input-font" :disabled"projectDisabled" placeholder"请选择" :readonly"isReadonly"><el-button slot"append"…

Office2019下载安装教程(2025最新永久方法)(附安装包)

文章目录 Office2019安装包下载Office2019一键安装步骤&#xff08;超详细&#xff01;&#xff09; 大家好&#xff01;今天给大家带来一篇超实用的Office2019专业版安装教程&#xff01;作为日常办公和学习的必备软件&#xff0c;Office的安装对很多朋友来说可能有点复杂&…

【编译工具】(版本控制)Git + GitHub Actions:自动化工作流如何让我的开发效率提升200%?

目录 引言&#xff1a;现代开发中版本控制和 CI/CD 的重要性 一、Git&#xff1a;为什么它是版本控制的首选&#xff1f; &#xff08;1&#xff09;Git 的核心优势 &#xff08;2&#xff09;Git 高效工作流示例 ① 功能开发流程 ② 紧急修复流程 二、GitHub Acti…

码蹄杯真题分享

我的个人主页 我的专栏&#xff1a; 人工智能领域、java-数据结构、Javase、C语言&#xff0c;MySQL&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01; 点赞&#x1f44d;收藏❤ 1&#xff1a;房间打扫&#xff08;题目链接&#xff09; 思路&#xff1a;要想…

小米玄戒O1架构深度解析(二):多核任务调度策略详解

上篇文章中&#xff0c;就提到了小米玄戒O1的多核任务调度策略&#xff0c;但讲得不够详细&#xff0c;尤其是对于完全公平调度器和能效感知调度&#xff0c;这次我们就深度剖析一下这两种调度策略。 目录 1. 完全公平调度器&#xff08;CFS&#xff09;1.1 完全公平调度基本原…

【技巧】win10和ubuntu互相挂在共享文件夹

回到目录 【技巧】win10和ubuntu互相挂在共享文件夹 1. ubuntu挂载win10共享文件夹 $ sudo apt update $ sudo apt install cifs-utils $ sudo mkdir /mnt/[这里改为ubuntu共享目录名] $ sudo mount -t cifs -o usernameadministrator //[这里改为win10机器IP]/[这里改为win…

线程(下)【Linux操作系统】

文章目录 线程控制线程共享进程地址空间中的所有数据线程会瓜分进程的时间片线程相关库函数库函数&#xff1a;pthread_create库函数&#xff1a;pthread_self库函数&#xff1a;pthread_join库函数&#xff1a;pthread_exit库函数&#xff1a;pthread_cancel[尽量少用]库函数&…