动手学深度学习(预备知识)
斩棘生. 2024-10-20 10:01:01 阅读 58
目录
1.安装
2.预备知识
2.1数据操作
2.11.Tensor基础
(1)Tensor定义
(2)GPU和CPU
(3)Tensor数据类型
(4)Tensor的创建
(5)数学运算
(6)索引和切片
(7)连接cat
(8)拆分chunk
2.12 常用的操作入门
2.13运算符
2.14广播机制
2.15索引和切片
2.16节省内存
2.17张量标量转换
2.2数据预处理
2.3线性代数
2.31标量
2.32向量
2.33张量
2.34降维
2.35点积
2.36矩阵向量积
2.37矩阵相乘
2.38范数
2.4微积分
2.41导数和微分
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的创建
共享内存....
<code>import torch
# 创建 形状为 2x3x4 的张量, 默认用 0 填充
t = torch.Tensor(2, 3, 4)
print(type(t)) # <class 'torch.Tensor'>
print(t.type()) # torch.FloatTensor
print(t.dtype) # torch.float32
print(t.size()) # torch.Size([2, 3, 4])
print(t.shape) # torch.Size([2, 3, 4])
print(t)
"""
tensor([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
"""
# 使用预先存在的数据 (Python序列 或 numpy.ndarray) 创建张量
t = torch.Tensor([[1, 2, 3], [4, 5, 6]])
print(t.dtype) # torch.float32
print(t)
"""
tensor([[1., 2., 3.],
[4., 5., 6.]])
"""
(5)数学运算
import torch
t = torch.zeros((2, 3)) # size 可以以 序列的形式传入, 也可以以 *size 的形式传入
print(t, t.dtype)
"""
tensor([[0., 0., 0.],
[0., 0., 0.]]) torch.float32
"""
t0 = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.int8)
t = torch.ones_like(t0) # size 和 dtype 都保持与 t0 一致
print(t)
"""
tensor([[1, 1, 1],
[1, 1, 1]], dtype=torch.int8) torch.int8
"""
t = torch.full((3, 5), 100)
print(t)
"""
tensor([[100, 100, 100, 100, 100],
[100, 100, 100, 100, 100],
[100, 100, 100, 100, 100]])
"""
t = torch.eye(3, 5)
print(t)
"""
tensor([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.]])
"""
t = torch.arange(0, 10, 1)
print(t)
"""
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
"""
t = torch.linspace(0, 10, 5)
print(t)
"""
tensor([ 0.0000, 2.5000, 5.0000, 7.5000, 10.0000])
"""
t = torch.rand((1, 5))
print(t)
"""
tensor([[0.7706, 0.1781, 0.2407, 0.4579, 0.0864]])
"""
t = torch.randint(0, 9, (3, 5))
print(t)
"""
tensor([[3, 4, 8, 2, 7],
[5, 8, 7, 0, 7],
[0, 0, 8, 1, 8]])
"""
t = torch.randn((3, 6))
print(t)
"""
tensor([[ 0.9932, -1.1636, -0.3698, -0.6131, 0.0571, 0.6054],
[-0.5878, -0.1389, -1.6374, -0.2527, 0.3637, -0.3284],
[-0.9119, 0.3085, 0.8913, 0.9905, 0.6498, -0.7845]])
"""
(6)索引和切片
可以参考csdn中tensor基础讲解,在此就不罗嗦了
(7)连接cat
同上
(8)拆分chunk
import torch
t = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]])
print(t.shape) # torch.Size([2, 5])
print(t)
"""
tensor([[1, 2, 3, 4],
[5, 6, 7, 8]])
"""
for x in torch.chunk(t, chunks=2, dim=0):
print(x)
"""
tensor([[1, 2, 3, 4]])
tensor([[5, 6, 7, 8]])
"""
for x in torch.chunk(t, chunks=2, dim=1):
print(x)
"""
tensor([[1, 2],
[5, 6]])
tensor([[3, 4],
[7, 8]])
"""
这里需要了解dim=0和等于1的区别
一个是 外维 一个是内维
dim范围是-2到1(在这里的范围)
dim范围和输入的维度有关
2.12 常用的操作入门
import torch
x=torch.arange(12)
print([x])
print(x.shape)
a=x.reshape(3,-1)
print(a)
y=x.reshape(3,4)
print(y)
print(y.shape)
print(y.numel())
print(torch.zeros(3,4))
print(torch.ones(3,4))
print(torch.randn(2,3,4))#随机梯度
print(torch.rand(9))#随机0,1
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运算符
<code>import torch
# x=torch.tensor([1,2,3,4])
# y=torch.tensor([5,6,7,8])
# print(x+y)
# print(x/y)
# print(x**y)
# print(x.exp())#指数
# print(torch.exp(y))
a=torch.arange(12,dtype=torch.float64).reshape(3,4)
b=torch.tensor([[4,3,2,1],[8,7,6,5],[4,3,2,1]])
print(a)
print(b)
print(a<b)
print(a==b)
# print(torch.cat((a,b),dim=0))#dim范围在-2到1
# print(torch.cat((a,b),dim=1))
# print(torch.cat((a,b),dim=-1))
# print(torch.cat((a,b),dim=-2))
print(a.sum())
这个运算结果就不展示了,大家自己动手探索一下
特别是cat的几种连接方式
2.14广播机制
广播机制就是两个形状不同的矩阵,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状
看上面图片,我用的是第一个矩阵加第二个矩阵哈,所以你一一对应,第一行就是0+0,0+1,0+2
第二行1+0,1+1,1+2以此类推
2.15索引和切片
<code>import torch
a=torch.arange(12,dtype=torch.float64).reshape(3,4)
# print(a)
# print(a[-1])
# print(a[1:3])
# a[0,1]=9
# print(a)
a[0:1,:1]=12
print(a)
a[0:1,:]=12
print(a)
a[0:1,-1:]=12
print(a)
注释部分的输出也在下面这个图片里
a[-1]就是最后一行
a[1:3]就是第二行和最后一行,记得是从1开始,但不包含3,如果把3改为2,那么就只输出第一行了,还有记得是从0开始计数
a[0,1]j就是把对应的位置数值进行修改
这里留一个问题,
a[0:1,-1:]=12
print(a)这行代码其实正常运行与下面图片输出不符,大家可以把a重置自己运行一遍
2.16节省内存
<code>import torch
a=torch.arange(12,dtype=torch.float64).reshape(3,4)
b=torch.tensor([[4,3,2,1],[8,7,6,5],[4,3,2,1]])
print(id(a))
c=torch.zeros_like(a)
print(id(c))
c[:]=a+b #c=a+b是不行的
print(id(c))
# a+=b
# print(id(a))
# a+=b
# print(id(a))
# a+=b
# print(id(a))
# a+=b
# print(id(a))
# a+=b
# print(id(a))
# for i in range(100): #重复了100次依旧没有改变
# a += b
# print(id(a))
运行一些操作可能会导致为新结果分配内存。 例如,如果我们用Y = X + Y
,我们将取消引用Y
指向的张量,而是指向新分配的内存处的张量
我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如Y[:] = <expression>
。 为了说明这一点,我们首先创建一个新的矩阵Z
,其形状与另一个Y
相同, 使用zeros_like
来分配一个全0的块。
如果在后续计算中没有重复使用X
, 我们也可以使用X[:] = X + Y
或X += Y
来减少操作的内存开销。
2.17张量标量转换
张量转标量用.item()
标量转张量用.tensor()【比如说一个numpy数组c,可以
d=torch.tensor(c)来转为张量
2.2数据预处理
数据预处理一般用pandas库
pandas库啊,你用用就知道咋样了
一般啊,你先用os库创建个文件夹,存放人工数据集
在一顿操作进行命名,然后求值的时候你可能会遇到求平均值.mean()好用多用
最后处理缺失值(NaN)
摘抄于书中便于大家理解(主要我有点瞌睡了,不好意思):通过位置索引iloc
,我们将data
分成inputs
和outputs
, 其中前者为data
的前两列,而后者为data
的最后一列。 对于inputs
中缺少的数值,我们用同一列的均值替换“NaN”项。
pandas库真是好库
Series:一维数组,可以存储任何数据类型(整数、字符串、浮点数、Python 对象等),每个元素都有一个标签(索引)。DataFrame:二维的、表格型的数据结构,可以看作是由多个 Series 组成的字典(共享同一个索引)
这是他的核心结构,第一次见他还是爬虫处理数据时,好久了啊,旧码重写,就像旧事重提。
2.3线性代数
明天更新啊哈哈
———————————————————————————————————————————
早上好朋友们 今天是7.10号,初中朋友要同学聚会,可惜这次去不了了...
2.31标量
标量由只有一个元素的张量表示
x = torch.tensor(3.0)
y = torch.tensor(2.0)
2.32向量
向量可以被视为标量值组成的列表。 这些标量值被称为向量的元素(element)或分量(component)
x = torch.arange(4)
2.33张量
基于 标量 向量 矩阵 来看张量,上述三个分别为零维,一维,二维张量
引入矩阵的转置概念:假设有一个3*4的矩阵,转置之后就成了4*3的矩阵
这个就是转置的样式,假设B=A转置,那么A【ij】=B【ji】
两个矩阵的按元素乘法称为Hadamard积(Hadamard product)
假设A和B都是3*4的有序矩阵,那么A*B的每一个结果就是A【ij】*B【ij】
tips:将张量乘以或加上一个标量不会改变张量的形状,其中张量的每个元素都将与标量相加或相乘
2.34降维
我们先理解axis
对矩阵内的元素我们常常使用求和操作,正常的.sum()会将矩阵内所有的元素进行求和
假设我们有一个形状为<code>(m, n, p)的三维张量,其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=0*0+1*1+2*2+3*3
2.37矩阵相乘
分析一下42=0*0+1*3+2*6+3*9也就是a矩阵的第一行元素与b向量的第一列元素分别相乘再求和
也就是进行第一个矩阵行数m*第二个矩阵列数n次向量积运算
2.38范数
矩阵范数分为四类:列范数,行范数,l2范数和F范数
1..列范数,就是每一列绝对值求和中的最大值
比如说这个矩阵求每一列绝对值求和为【6,14,4】
那么列范数就是14
2.行范数,就是每一行绝对值求和中的最大值
依旧按上面矩阵为例每一行绝对值求和为【8,3,13】
3. 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.的报错
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"#在程序中发现了多个 OpenMP 运行时库的初始化。这可能会导致性能下降或产生错误结果,因为多个运行时库之间的交互可能会导致混乱。
#上述代码可以避免报错
以f(x)=3x**2-4*x为例,内容都体现在代码注释里了
<code>import torch
import numpy as np
from matplotlib_inline import backend_inline
from matplotlib import pyplot as plt
from d2l import torch as d2l
def f(x):
return 3 * x ** 2 - 4 * x
def numerical_lim(f, x, h):
return (f(x + h) - f(x)) / h
h = 0.1
for i in range(5):
print(f'h={h:.5f}, numerical limit={numerical_lim(f, 1, h):.5f}')
h *= 0.1#使h接近于0
def use_svg_display(): #@save
"""使用svg格式在Jupyter中显示绘图"""
backend_inline.set_matplotlib_formats('svg')
def set_figsize(figsize=(3.5, 2.5)):
"""设置matplotlib的图表大小"""
use_svg_display()
d2l.plt.rcParams['figure.figsize'] = figsize
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
"""设置matplotlib的轴
设置matplotlib Axes对象的属性。
参数:
axes (matplotlib.axes.Axes): 需要设置的Axes对象。
xlabel (str): X轴的标签。
ylabel (str): Y轴的标签。
xlim (tuple): X轴的范围,格式为(最小值, 最大值)。
ylim (tuple): Y轴的范围,格式为(最小值, 最大值)。
xscale (str): X轴的比例尺,如'linear', 'log'等。线性比例尺和对数比例尺
yscale (str): Y轴的比例尺,如'linear', 'log'等。
legend (list of tuples, optional): 图例项,格式为[(label1, line1), (label2, line2), ...]
其中label是字符串,line是Axes上的线对象。
"""
axes.set_xlabel(xlabel)
axes.set_ylabel(ylabel)
axes.set_xscale(xscale)
axes.set_yscale(yscale)
axes.set_xlim(xlim)
axes.set_ylim(ylim)
if legend:
axes.legend(legend)
axes.grid()#添加网格线
#@save
def plot(X, Y=None, xlabel=None, ylabel=None, legend=None, xlim=None,
ylim=None, xscale='linear', yscale='linear',#linear指的是线性刻度code>
fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5), axes=None):
# ax.plot(x, y1, fmts[0], label='Data 1') # 使用'-'线型code>
# ax.plot(x, y2, fmts[1], label='Data 2') # 使用'm--'线型,m代表品红色code>
# ax.plot(x, y3, fmts[2], label='Data 3') # 使用'g-.'线型,g代表绿色code>
# ax.plot(x, y4, fmts[3], label='Data 4') # 使用'r:'线型,r代表红色code>
"""绘制数据点"""
if legend is None:
legend = []
set_figsize(figsize)
axes = axes if axes else d2l.plt.gca()#获取当前坐标轴
# 如果X有一个轴,输出True
def has_one_axis(X):
return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list)
and not hasattr(X[0], "__len__"))
'''
hasattr(X, "ndim") and X.ndim == 1:
这部分首先检查X是否具有ndim属性。在NumPy数组中,ndim属性表示数组的维度数。
如果X具有ndim属性,并且X.ndim == 1,即X是一个一维数组,那么这部分条件为真。
isinstance(X, list) and not hasattr(X[0], "__len__"):
这部分首先检查X是否是一个列表(list)。
如果X是列表,接下来检查列表中的第一个元素(X[0])是否没有__len__方法。在Python中,许多容器类型(如列表、元组、字符串等)都有__len__方法,用于返回容器中元素的数量。如果一个对象没有__len__方法,那么它通常不是容器类型,也就是说,它不是另一个列表、元组、字符串等。
如果X是列表,并且其第一个元素不是容器类型(即没有__len__方法),那么这部分条件为真。'''
if has_one_axis(X):
X = [X]
if Y is None:
X, Y = [[]] * len(X), X
'''
X, Y = [[]] * len(X), X:这行代码做了两件事。
首先,它创建了一个与X长度相同的列表列表(二维列表),其中每个内部列表都是空的([[]] * len(X))。
然后,它将原始的X赋值给Y。'''
elif has_one_axis(Y):
Y = [Y]
if len(X) != len(Y):
X = X * len(Y)
axes.cla()#清除坐标轴内容
for x, y, fmt in zip(X, Y, fmts):
if len(x):
axes.plot(x, y, fmt)
else:
axes.plot(y, fmt)
set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
x = np.arange(0, 3, 0.1)
plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
plt.show()
2.42偏导数和梯度
一、定义
偏导数(Partial Derivative):
偏导数用于多变量函数,它描述了函数在一个特定变量方向上的变化率,而其他变量保持不变。例如,对于函数f(x,y),其关于x的偏导数表示为∂x∂f,关于y的偏导数表示为∂y∂f。梯度(Gradient):
梯度是一个矢量,它包含了一个多变量函数所有偏导数的信息。对于函数f(x,y),其梯度是一个二维向量,表示为∇f=(∂x∂f,∂y∂f)。对于更高维的函数f(x1,x2,…,xn),其梯度则是一个n维向量。
二、关系
梯度是偏导数的向量形式:
梯度将函数在各个方向上的偏导数组合成一个向量,这个向量在几何上表示了函数在该点处变化最快的方向。因此,可以说梯度是偏导数的集合,以向量的形式呈现。梯度方向与变化率:
梯度的方向是函数在该点处变化最快的方向(即最陡峭的方向),而梯度的模(长度)则表示了这种变化率的大小。换句话说,梯度不仅告诉我们函数在哪个方向上变化最快,还告诉我们这种变化的速度有多快
可以参考哔哩哔哩中的梯度动画进行理解
2.43自动微分
import torch
x = torch.arange(4.0)
x
x.requires_grad_(True) # 等价于x=torch.arange(4.0,requires_grad=True)
x.grad # 默认值是None
x.requires_grad_是在设置随后的操作之后能够计算x的梯度
x.grad是存储x的梯度
y = 2 * torch.dot(x, x)
y
然后x
是一个长度为4的向量,计算x
和x
的点积,得到了我们赋值给y
的标量输出。 接下来,通过调用反向传播函数来自动计算y
关于x
每个分量的梯度,并打印这些梯度。
y.backward()
x.grad
tips:在PyTorch中,每次调用.backward()
后,PyTorch会保留计算的梯度,但如果你再次调用.backward()
而不先清零梯度(使用optimizer.zero_grad()
或x.grad.zero_()
),PyTorch会累加梯度而不是覆盖它们。然而,这通常不会导致x.grad
为None
,除非在调用.backward()
之前或之后显式地将x.grad
设置为None
。
另外x得为向量,标量可不行
2.44分离计算
z与y,x有关,y与x有关
z与两个变量有关,想求x的偏导,就得先用一个u存放y的数值视作常数。
x.grad.zero_()
y = x * x
u = y.detach()
z = u * x
z.sum().backward()
x.grad == u
.detach()就是创建一个与y一样的张量给u
计算图(Computational Graph)是一个用于表示和存储所有操作(如加法、乘法、激活函数等)及其依赖关系的结构。当你对张量(Tensor)进行操作时,PyTorch会自动构建一个计算图来跟踪这些操作。这个计算图对于自动微分(Automatic Differentiation)至关重要,因为它允许PyTorch在需要时反向遍历图来计算梯度。
就是啥吧,你z只想影响x,不想影响y与x的梯度,这个时候就需要u暂时顶替一下
x成绩不好,z是老师要找家长,x怕父母知道了影响家庭和睦,所以找来u来充当父母去跟老师谈话。
2.5概率
求我现在是否晚饭的概率
先掷一个骰子吧
fair_probs = torch.ones([6]) / 6
multinomial.Multinomial(1, fair_probs).sample()
.sample()是把样本都取出来
6个样本只有一个是1其他都是0
multinomial.Multinomial(10, fair_probs).sample()
这个的话就是掷10次骰子看每个反向的次数
如果是概率的话就除以掷的次数
2.51概率论知识
1.任意概率不为0
2.总概率为1
3.联合概率,也就是a和b同时发生
4.贝叶斯定理
想象你是一位侦探,正在调查一起案件。你有两个嫌疑人,我们称他们为A和B。在没有进一步证据的情况下,你根据初步调查认为A和B的作案嫌疑是相等的,即各占50%的嫌疑。然而,随着调查的深入,你发现了一些新的线索,这些线索可能与案件有关,也可能与嫌疑人有关。
贝叶斯定理的比喻:
先验概率:在没有新线索之前,你认为A和B的作案嫌疑各为50%。这里的50%就是先验概率,它是你根据已知信息(即初步调查)对事件发生的概率所做的估计。
新线索(证据):调查过程中,你发现了一个重要的指纹线索,经过比对发现该指纹与嫌疑人A的指纹相匹配。这个指纹线索就是新的证据,它会影响你对A和B作案嫌疑的判断。
似然率(调整因子):指纹线索与A相匹配这一事实,增加了A作案的可能性,同时降低了B作案的可能性。这个增加或减少的比例就是似然率或调整因子。在这个比喻中,似然率可能非常高,因为指纹是高度个人化的证据。
后验概率:结合先验概率和新线索的似然率,你可以计算出在发现指纹线索后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) 是指纹线索出现的总概率,它可以通过全概率公式计算得到。
期望和方差呢,都蛮不错的
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。