0


动手学深度学习(预备知识)

1.安装

下面这个网址有具体安装步骤

【PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】】https://www.bilibili.com/video/BV1hE411t7RN?vd_source=1b9a0d7cc95ffe0bada9111b709b98a4

https://zh-v2.d2l.ai/chapter_installation/index.html

笔者用的是conda环境的pytorch,大家也记得装一下,讲解的代码都是基于pytorch的。

如果想要其他替换的代码,可以自主在上面链接书中找一下。

如果安装不懂的后台踢就行

2.预备知识

2.1数据操作

2.11.Tensor基础

(1)Tensor定义

中文名字叫做张量(可以视为多维数组)

基于 标量 向量 矩阵 来看张量,上述三个分别为零维,一维,二维张量

(2)GPU和CPU
  • CPU:CPU更适合处理复杂逻辑和少量线程的计算任务。它拥有少量的核心,但每个核心都能处理复杂的任务和逻辑。在处理逻辑复杂、条件分支多的任务上,CPU具有优势。然而,在处理深度学习中大量并行计算任务时,CPU的效率相对较低。由于CPU并非专为大规模并行计算设计,其计算速度在处理这类任务时可能无法满足需求。
  • GPU:GPU则专为并行计算而设计,拥有大量的小核心,这些小核心适合并行执行相似的任务。在深度学习中,GPU针对大量并行处理的任务(如矩阵乘法、卷积等)表现出色,可以大大缩短计算时间。GPU的并行计算能力在处理深度学习中的计算密集型任务时,通常远超CPU,能够提供更高的计算效率。
(3)Tensor数据类型

分为GPU和CPU两种变体

在PyTorch中,量化是一种将浮点计算转换为定点计算的技术,旨在减少模型的大小、加速推理过程,同时尽量保持模型的精度

以下是一些基本操作

(4)Tensor的创建

共享内存....

  1. import torch
  2. # 创建 形状为 2x3x4 的张量, 默认用 0 填充
  3. t = torch.Tensor(2, 3, 4)
  4. print(type(t)) # <class 'torch.Tensor'>
  5. print(t.type()) # torch.FloatTensor
  6. print(t.dtype) # torch.float32
  7. print(t.size()) # torch.Size([2, 3, 4])
  8. print(t.shape) # torch.Size([2, 3, 4])
  9. print(t)
  10. """
  11. tensor([[[0., 0., 0., 0.],
  12. [0., 0., 0., 0.],
  13. [0., 0., 0., 0.]],
  14. [[0., 0., 0., 0.],
  15. [0., 0., 0., 0.],
  16. [0., 0., 0., 0.]]])
  17. """
  18. # 使用预先存在的数据 (Python序列 或 numpy.ndarray) 创建张量
  19. t = torch.Tensor([[1, 2, 3], [4, 5, 6]])
  20. print(t.dtype) # torch.float32
  21. print(t)
  22. """
  23. tensor([[1., 2., 3.],
  24. [4., 5., 6.]])
  25. """
(5)数学运算
  1. import torch
  2. t = torch.zeros((2, 3)) # size 可以以 序列的形式传入, 也可以以 *size 的形式传入
  3. print(t, t.dtype)
  4. """
  5. tensor([[0., 0., 0.],
  6. [0., 0., 0.]]) torch.float32
  7. """
  8. t0 = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.int8)
  9. t = torch.ones_like(t0) # size 和 dtype 都保持与 t0 一致
  10. print(t)
  11. """
  12. tensor([[1, 1, 1],
  13. [1, 1, 1]], dtype=torch.int8) torch.int8
  14. """
  15. t = torch.full((3, 5), 100)
  16. print(t)
  17. """
  18. tensor([[100, 100, 100, 100, 100],
  19. [100, 100, 100, 100, 100],
  20. [100, 100, 100, 100, 100]])
  21. """
  22. t = torch.eye(3, 5)
  23. print(t)
  24. """
  25. tensor([[1., 0., 0., 0., 0.],
  26. [0., 1., 0., 0., 0.],
  27. [0., 0., 1., 0., 0.]])
  28. """
  29. t = torch.arange(0, 10, 1)
  30. print(t)
  31. """
  32. tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
  33. """
  34. t = torch.linspace(0, 10, 5)
  35. print(t)
  36. """
  37. tensor([ 0.0000, 2.5000, 5.0000, 7.5000, 10.0000])
  38. """
  39. t = torch.rand((1, 5))
  40. print(t)
  41. """
  42. tensor([[0.7706, 0.1781, 0.2407, 0.4579, 0.0864]])
  43. """
  44. t = torch.randint(0, 9, (3, 5))
  45. print(t)
  46. """
  47. tensor([[3, 4, 8, 2, 7],
  48. [5, 8, 7, 0, 7],
  49. [0, 0, 8, 1, 8]])
  50. """
  51. t = torch.randn((3, 6))
  52. print(t)
  53. """
  54. tensor([[ 0.9932, -1.1636, -0.3698, -0.6131, 0.0571, 0.6054],
  55. [-0.5878, -0.1389, -1.6374, -0.2527, 0.3637, -0.3284],
  56. [-0.9119, 0.3085, 0.8913, 0.9905, 0.6498, -0.7845]])
  57. """
(6)索引和切片

可以参考csdn中tensor基础讲解,在此就不罗嗦了

(7)连接cat
  1. 同上
(8)拆分chunk
  1. import torch
  2. t = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]])
  3. print(t.shape) # torch.Size([2, 5])
  4. print(t)
  5. """
  6. tensor([[1, 2, 3, 4],
  7. [5, 6, 7, 8]])
  8. """
  9. for x in torch.chunk(t, chunks=2, dim=0):
  10. print(x)
  11. """
  12. tensor([[1, 2, 3, 4]])
  13. tensor([[5, 6, 7, 8]])
  14. """
  15. for x in torch.chunk(t, chunks=2, dim=1):
  16. print(x)
  17. """
  18. tensor([[1, 2],
  19. [5, 6]])
  20. tensor([[3, 4],
  21. [7, 8]])
  22. """

这里需要了解dim=0和等于1的区别

一个是 外维 一个是内维

dim范围是-2到1(在这里的范围)

dim范围和输入的维度有关

2.12 常用的操作入门

  1. import torch
  2. x=torch.arange(12)
  3. print([x])
  4. print(x.shape)
  5. a=x.reshape(3,-1)
  6. print(a)
  7. y=x.reshape(3,4)
  8. print(y)
  9. print(y.shape)
  10. print(y.numel())
  11. print(torch.zeros(3,4))
  12. print(torch.ones(3,4))
  13. print(torch.randn(2,3,4))#随机梯度
  14. print(torch.rand(9))#随机01

arange(12)表示0到11顺序的矩阵

print([x])是在print(x)整体的输出在加[]而不是仅仅在矩阵外面加一层括号

x.shape表示这个矩阵的大小,比如x就是一维矩阵,而y就是3*4的矩阵

x.reshape(3,4)表示把一维矩阵转换为二维矩阵,好用多用,但是记得两个矩阵的元素数量需要相同不然就报错了

x.reshape(3,-1)等同于x.reshape(3,4)也等同于x.reshape(-1,4),因为上面我们以及定义了x的元素个数总共有12个,所以给定矩阵的行数或者列数的一个,系统自动就转换了

后面的东西前面都见过了就不赘述了

2.13运算符

  1. import torch
  2. # x=torch.tensor([1,2,3,4])
  3. # y=torch.tensor([5,6,7,8])
  4. # print(x+y)
  5. # print(x/y)
  6. # print(x**y)
  7. # print(x.exp())#指数
  8. # print(torch.exp(y))
  9. a=torch.arange(12,dtype=torch.float64).reshape(3,4)
  10. b=torch.tensor([[4,3,2,1],[8,7,6,5],[4,3,2,1]])
  11. print(a)
  12. print(b)
  13. print(a<b)
  14. print(a==b)
  15. # print(torch.cat((a,b),dim=0))#dim范围在-2到1
  16. # print(torch.cat((a,b),dim=1))
  17. # print(torch.cat((a,b),dim=-1))
  18. # print(torch.cat((a,b),dim=-2))
  19. print(a.sum())

这个运算结果就不展示了,大家自己动手探索一下

特别是cat的几种连接方式

2.14广播机制

广播机制就是两个形状不同的矩阵,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状

看上面图片,我用的是第一个矩阵加第二个矩阵哈,所以你一一对应,第一行就是0+0,0+1,0+2

第二行1+0,1+1,1+2以此类推

2.15索引和切片

  1. import torch
  2. a=torch.arange(12,dtype=torch.float64).reshape(3,4)
  3. # print(a)
  4. # print(a[-1])
  5. # print(a[1:3])
  6. # a[0,1]=9
  7. # print(a)
  8. a[0:1,:1]=12
  9. print(a)
  10. a[0:1,:]=12
  11. print(a)
  12. a[0:1,-1:]=12
  13. print(a)

注释部分的输出也在下面这个图片里

a[-1]就是最后一行

a[1:3]就是第二行和最后一行,记得是从1开始,但不包含3,如果把3改为2,那么就只输出第一行了,还有记得是从0开始计数

a[0,1]j就是把对应的位置数值进行修改

这里留一个问题,

  1. a[0:1,-1:]=12
  2. print(a)这行代码其实正常运行与下面图片输出不符,大家可以把a重置自己运行一遍

2.16节省内存

  1. import torch
  2. a=torch.arange(12,dtype=torch.float64).reshape(3,4)
  3. b=torch.tensor([[4,3,2,1],[8,7,6,5],[4,3,2,1]])
  4. print(id(a))
  5. c=torch.zeros_like(a)
  6. print(id(c))
  7. c[:]=a+b #c=a+b是不行的
  8. print(id(c))
  9. # a+=b
  10. # print(id(a))
  11. # a+=b
  12. # print(id(a))
  13. # a+=b
  14. # print(id(a))
  15. # a+=b
  16. # print(id(a))
  17. # a+=b
  18. # print(id(a))
  19. # for i in range(100): #重复了100次依旧没有改变
  20. # a += b
  21. # print(id(a))

运行一些操作可能会导致为新结果分配内存。 例如,如果我们用

  1. Y = X + Y

,我们将取消引用

  1. Y

指向的张量,而是指向新分配的内存处的张量

我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如

  1. Y[:] = <expression>

。 为了说明这一点,我们首先创建一个新的矩阵

  1. Z

,其形状与另一个

  1. Y

相同, 使用

  1. zeros_like

来分配一个全0的块。

如果在后续计算中没有重复使用

  1. X

, 我们也可以使用

  1. X[:] = X + Y

  1. X += Y

来减少操作的内存开销。

2.17张量标量转换

张量转标量用.item()

标量转张量用.tensor()【比如说一个numpy数组c,可以

  1. d=torch.tensor(c)来转为张量

2.2数据预处理

数据预处理一般用pandas库

pandas库啊,你用用就知道咋样了

一般啊,你先用os库创建个文件夹,存放人工数据集

在一顿操作进行命名,然后求值的时候你可能会遇到求平均值.mean()好用多用

最后处理缺失值(NaN)

摘抄于书中便于大家理解(主要我有点瞌睡了,不好意思):通过位置索引

  1. iloc

,我们将

  1. data

分成

  1. inputs

  1. outputs

, 其中前者为

  1. data

的前两列,而后者为

  1. data

的最后一列。 对于

  1. inputs

中缺少的数值,我们用同一列的均值替换“NaN”项。

pandas库真是好库

  • Series:一维数组,可以存储任何数据类型(整数、字符串、浮点数、Python 对象等),每个元素都有一个标签(索引)。
  • DataFrame:二维的、表格型的数据结构,可以看作是由多个 Series 组成的字典(共享同一个索引)

这是他的核心结构,第一次见他还是爬虫处理数据时,好久了啊,旧码重写,就像旧事重提。

2.3线性代数

明天更新啊哈哈

———————————————————————————————————————————

早上好朋友们 今天是7.10号,初中朋友要同学聚会,可惜这次去不了了...

2.31标量

标量由只有一个元素的张量表示

  1. x = torch.tensor(3.0)
  2. y = torch.tensor(2.0)

2.32向量

向量可以被视为标量值组成的列表。 这些标量值被称为向量的元素(element)或分量(component)

  1. x = torch.arange(4)

2.33张量

基于 标量 向量 矩阵 来看张量,上述三个分别为零维,一维,二维张量

引入矩阵的转置概念:假设有一个34的矩阵,转置之后就成了43的矩阵

这个就是转置的样式,假设B=A转置,那么A【ij】=B【ji】

两个矩阵的按元素乘法称为Hadamard积(Hadamard product)

假设A和B都是34的有序矩阵,那么AB的每一个结果就是A【ij】*B【ij】

tips:将张量乘以或加上一个标量不会改变张量的形状,其中张量的每个元素都将与标量相加或相乘

2.34降维

我们先理解axis

对矩阵内的元素我们常常使用求和操作,正常的.sum()会将矩阵内所有的元素进行求和

假设我们有一个形状为

  1. (m, n, p)

的三维张量,其

  1. axis

的范围可以解释如下:

  • axis = 0:沿着第一个维度(大小为m的维度)进行操作。
  • axis = 1:沿着第二个维度(大小为n的维度)进行操作。
  • axis = 2:沿着第三个维度(大小为p的维度)进行操作。
  • axis = -1:与axis = 2相同,也是沿着第三个维度(大小为p的维度)进行操作。
  • axis = -2:沿着第二个维度(大小为n的维度)进行操作,与axis = 1相同

然后我们以实际例子来验证

由结果不难发现,axis=0时把(2,3,4)中的2压缩了,生成了一个(3,4)的矩阵

大家可以试试更多维度的张量,axis范围处于最大维度的正负数之间

2.35点积

这个就是x,y向量点积的表示方法

点积的结果:相同位置的按元素乘积的和

torch.dot(x,y)为代码形式

2.36矩阵向量积

学会了点积就会向量积了

a的行向量中每一个元素与相对应的b的元素相乘再加和得到向量积输出

比如说14=00+11+22+33

2.37矩阵相乘

分析一下42=00+13+26+39也就是a矩阵的第一行元素与b向量的第一列元素分别相乘再求和

也就是进行第一个矩阵行数m*第二个矩阵列数n次向量积运算

2.38范数

矩阵范数分为四类:列范数,行范数,l2范数和F范数

1..列范数,就是每一列绝对值求和中的最大值

比如说这个矩阵求每一列绝对值求和为【6,14,4】

那么列范数就是14

2.行范数,就是每一行绝对值求和中的最大值

依旧按上面矩阵为例每一行绝对值求和为【8,3,13】

  1. 2范数

矩阵a转置a的最大特征值下的平方根

先算a转置*a

入e-a=0转置a中入为最大特征值

求这个入是线代中求特征值的

4.F范数就是各个元素平方和再开根

2.4微积分

2.41导数和微分

这里提一个东西

如果出现:OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.的报错

  1. import os
  2. os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"#在程序中发现了多个 OpenMP 运行时库的初始化。这可能会导致性能下降或产生错误结果,因为多个运行时库之间的交互可能会导致混乱。
  3. #上述代码可以避免报错

以f(x)=3x*2-4x为例,内容都体现在代码注释里了

  1. import torch
  2. import numpy as np
  3. from matplotlib_inline import backend_inline
  4. from matplotlib import pyplot as plt
  5. from d2l import torch as d2l
  6. def f(x):
  7. return 3 * x ** 2 - 4 * x
  8. def numerical_lim(f, x, h):
  9. return (f(x + h) - f(x)) / h
  10. h = 0.1
  11. for i in range(5):
  12. print(f'h={h:.5f}, numerical limit={numerical_lim(f, 1, h):.5f}')
  13. h *= 0.1#使h接近于0
  14. def use_svg_display(): #@save
  15. """使用svg格式在Jupyter中显示绘图"""
  16. backend_inline.set_matplotlib_formats('svg')
  17. def set_figsize(figsize=(3.5, 2.5)):
  18. """设置matplotlib的图表大小"""
  19. use_svg_display()
  20. d2l.plt.rcParams['figure.figsize'] = figsize
  21. def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
  22. """设置matplotlib的轴
  23. 设置matplotlib Axes对象的属性。
  24. 参数:
  25. axes (matplotlib.axes.Axes): 需要设置的Axes对象。
  26. xlabel (str): X轴的标签。
  27. ylabel (str): Y轴的标签。
  28. xlim (tuple): X轴的范围,格式为(最小值, 最大值)。
  29. ylim (tuple): Y轴的范围,格式为(最小值, 最大值)。
  30. xscale (str): X轴的比例尺,如'linear', 'log'等。线性比例尺和对数比例尺
  31. yscale (str): Y轴的比例尺,如'linear', 'log'等。
  32. legend (list of tuples, optional): 图例项,格式为[(label1, line1), (label2, line2), ...]
  33. 其中label是字符串,line是Axes上的线对象。
  34. """
  35. axes.set_xlabel(xlabel)
  36. axes.set_ylabel(ylabel)
  37. axes.set_xscale(xscale)
  38. axes.set_yscale(yscale)
  39. axes.set_xlim(xlim)
  40. axes.set_ylim(ylim)
  41. if legend:
  42. axes.legend(legend)
  43. axes.grid()#添加网格线
  44. #@save
  45. def plot(X, Y=None, xlabel=None, ylabel=None, legend=None, xlim=None,
  46. ylim=None, xscale='linear', yscale='linear',#linear指的是线性刻度
  47. fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5), axes=None):
  48. # ax.plot(x, y1, fmts[0], label='Data 1') # 使用'-'线型
  49. # ax.plot(x, y2, fmts[1], label='Data 2') # 使用'm--'线型,m代表品红色
  50. # ax.plot(x, y3, fmts[2], label='Data 3') # 使用'g-.'线型,g代表绿色
  51. # ax.plot(x, y4, fmts[3], label='Data 4') # 使用'r:'线型,r代表红色
  52. """绘制数据点"""
  53. if legend is None:
  54. legend = []
  55. set_figsize(figsize)
  56. axes = axes if axes else d2l.plt.gca()#获取当前坐标轴
  57. # 如果X有一个轴,输出True
  58. def has_one_axis(X):
  59. return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list)
  60. and not hasattr(X[0], "__len__"))
  61. '''
  62. hasattr(X, "ndim") and X.ndim == 1:
  63. 这部分首先检查X是否具有ndim属性。在NumPy数组中,ndim属性表示数组的维度数。
  64. 如果X具有ndim属性,并且X.ndim == 1,即X是一个一维数组,那么这部分条件为真。
  65. isinstance(X, list) and not hasattr(X[0], "__len__"):
  66. 这部分首先检查X是否是一个列表(list)。
  67. 如果X是列表,接下来检查列表中的第一个元素(X[0])是否没有__len__方法。在Python中,许多容器类型(如列表、元组、字符串等)都有__len__方法,用于返回容器中元素的数量。如果一个对象没有__len__方法,那么它通常不是容器类型,也就是说,它不是另一个列表、元组、字符串等。
  68. 如果X是列表,并且其第一个元素不是容器类型(即没有__len__方法),那么这部分条件为真。'''
  69. if has_one_axis(X):
  70. X = [X]
  71. if Y is None:
  72. X, Y = [[]] * len(X), X
  73. '''
  74. X, Y = [[]] * len(X), X:这行代码做了两件事。
  75. 首先,它创建了一个与X长度相同的列表列表(二维列表),其中每个内部列表都是空的([[]] * len(X))。
  76. 然后,它将原始的X赋值给Y。'''
  77. elif has_one_axis(Y):
  78. Y = [Y]
  79. if len(X) != len(Y):
  80. X = X * len(Y)
  81. axes.cla()#清除坐标轴内容
  82. for x, y, fmt in zip(X, Y, fmts):
  83. if len(x):
  84. axes.plot(x, y, fmt)
  85. else:
  86. axes.plot(y, fmt)
  87. set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
  88. x = np.arange(0, 3, 0.1)
  89. plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
  90. plt.show()

2.42偏导数和梯度

一、定义

  1. 偏导数(Partial Derivative): - 偏导数用于多变量函数,它描述了函数在一个特定变量方向上的变化率,而其他变量保持不变。- 例如,对于函数f(x,y),其关于x的偏导数表示为∂x∂f​,关于y的偏导数表示为∂y∂f​。
  2. 梯度(Gradient): - 梯度是一个矢量,它包含了一个多变量函数所有偏导数的信息。- 对于函数f(x,y),其梯度是一个二维向量,表示为∇f=(∂x∂f​,∂y∂f​)。对于更高维的函数f(x1​,x2​,…,xn​),其梯度则是一个n维向量。 ---

二、关系

  1. 梯度是偏导数的向量形式: - 梯度将函数在各个方向上的偏导数组合成一个向量,这个向量在几何上表示了函数在该点处变化最快的方向。- 因此,可以说梯度是偏导数的集合,以向量的形式呈现。
  2. 梯度方向与变化率: - 梯度的方向是函数在该点处变化最快的方向(即最陡峭的方向),而梯度的模(长度)则表示了这种变化率的大小。- 换句话说,梯度不仅告诉我们函数在哪个方向上变化最快,还告诉我们这种变化的速度有多快

可以参考哔哩哔哩中的梯度动画进行理解

2.43自动微分

  1. import torch
  2. x = torch.arange(4.0)
  3. x
  4. x.requires_grad_(True) # 等价于x=torch.arange(4.0,requires_grad=True)
  5. x.grad # 默认值是None

x.requires_grad_是在设置随后的操作之后能够计算x的梯度

x.grad是存储x的梯度

  1. y = 2 * torch.dot(x, x)
  2. y

然后

  1. x

是一个长度为4的向量,计算

  1. x

  1. x

的点积,得到了我们赋值给

  1. y

的标量输出。 接下来,通过调用反向传播函数来自动计算

  1. y

关于

  1. x

每个分量的梯度,并打印这些梯度。

  1. y.backward()
  2. x.grad

tips:在PyTorch中,每次调用

  1. .backward()

后,PyTorch会保留计算的梯度,但如果你再次调用

  1. .backward()

而不先清零梯度(使用

  1. optimizer.zero_grad()

  1. x.grad.zero_()

),PyTorch会累加梯度而不是覆盖它们。然而,这通常不会导致

  1. x.grad

  1. None

,除非在调用

  1. .backward()

之前或之后显式地将

  1. x.grad

设置为

  1. None

另外x得为向量,标量可不行

2.44分离计算

z与y,x有关,y与x有关

z与两个变量有关,想求x的偏导,就得先用一个u存放y的数值视作常数。

  1. x.grad.zero_()
  2. y = x * x
  3. u = y.detach()
  4. z = u * x
  5. z.sum().backward()
  6. x.grad == u

.detach()就是创建一个与y一样的张量给u

计算图(Computational Graph)是一个用于表示和存储所有操作(如加法、乘法、激活函数等)及其依赖关系的结构。当你对张量(Tensor)进行操作时,PyTorch会自动构建一个计算图来跟踪这些操作。这个计算图对于自动微分(Automatic Differentiation)至关重要,因为它允许PyTorch在需要时反向遍历图来计算梯度。

就是啥吧,你z只想影响x,不想影响y与x的梯度,这个时候就需要u暂时顶替一下

x成绩不好,z是老师要找家长,x怕父母知道了影响家庭和睦,所以找来u来充当父母去跟老师谈话。

2.5概率

求我现在是否晚饭的概率

先掷一个骰子吧

  1. fair_probs = torch.ones([6]) / 6
  2. multinomial.Multinomial(1, fair_probs).sample()

.sample()是把样本都取出来

6个样本只有一个是1其他都是0

  1. multinomial.Multinomial(10, fair_probs).sample()

这个的话就是掷10次骰子看每个反向的次数

如果是概率的话就除以掷的次数

2.51概率论知识

1.任意概率不为0

2.总概率为1

3.联合概率,也就是a和b同时发生

4.贝叶斯定理

想象你是一位侦探,正在调查一起案件。你有两个嫌疑人,我们称他们为A和B。在没有进一步证据的情况下,你根据初步调查认为A和B的作案嫌疑是相等的,即各占50%的嫌疑。然而,随着调查的深入,你发现了一些新的线索,这些线索可能与案件有关,也可能与嫌疑人有关。

贝叶斯定理的比喻

  1. 先验概率:在没有新线索之前,你认为A和B的作案嫌疑各为50%。这里的50%就是先验概率,它是你根据已知信息(即初步调查)对事件发生的概率所做的估计。
  2. 新线索(证据):调查过程中,你发现了一个重要的指纹线索,经过比对发现该指纹与嫌疑人A的指纹相匹配。这个指纹线索就是新的证据,它会影响你对A和B作案嫌疑的判断。
  3. 似然率(调整因子):指纹线索与A相匹配这一事实,增加了A作案的可能性,同时降低了B作案的可能性。这个增加或减少的比例就是似然率或调整因子。在这个比喻中,似然率可能非常高,因为指纹是高度个人化的证据。
  4. 后验概率:结合先验概率和新线索的似然率,你可以计算出在发现指纹线索后A和B的作案嫌疑。这个新的嫌疑比例就是后验概率。由于指纹线索与A高度匹配,因此A的后验概率会远高于50%,而B的后验概率则会相应降低。

具体计算

虽然在这个比喻中我们没有进行具体的数值计算,但贝叶斯定理的公式可以帮助我们进行这样的计算。如果设A作案为事件A,指纹线索为事件B,则贝叶斯定理可以表示为:

P(A|B) = P(B|A) * P(A) / P(B)

其中:

  • P(A|B) 是后验概率,即在发现指纹线索后A作案的概率。
  • P(B|A) 是似然率,即如果A作案,则发现指纹线索的概率。
  • P(A) 是先验概率,即在没有新线索之前A作案的概率。
  • P(B) 是指纹线索出现的总概率,它可以通过全概率公式计算得到。

期望和方差呢,都蛮不错的


本文转载自: https://blog.csdn.net/Q268191051011/article/details/140302737
版权归原作者 斩棘生. 所有, 如有侵权,请联系我们删除。

“动手学深度学习(预备知识)”的评论:

还没有评论