Python进阶二: NumPy基础:数组和矢量计算

news2024/11/24 6:18:28

二、NumPy基础:数组和矢量计算

本文源自微博客(www.microblog.store),且以获得授权

NumPy(Numerical Python的简称)是Python数值计算最重要的基础包。大多数提供科学计算的包都是用NumPy的数组作为构建基础。

NumPy的部分功能如下:

  • ndarray,一个具有矢量算术运算和复杂广播能⼒的快速且节省空间的多维数组。
  • 用于对整组数据进行快速运算的标准数学函数(⽆需编写循环)。
  • 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。
  • 线性代数、随机数生成以及傅⾥叶变换功能。
  • 用于集成由C、C++、Fortran等语言编写的代码的A C API。

由于NumPy提供了一个简单易用的C API,因此很容易将数据传递给由低级语言编写的外部库,外部库也能以NumPy数组的形式将数据返回给Python。这个功能使Python成为一种包装C/C++/Fortran历史代码库的选择,并使被包装库拥有一个动态的、易用的接口。

NumPy本身并没有提供多么高级的数据分析功能,理解NumPy数组以及面向数组的计算将有助于你更加高效地使用诸如pandas之类的工具。因为NumPy是一个很大的题目,我会在附录A中介绍更多NumPy高级功能,比如广播。

对于大部分数据分析应用而言,我最关注的功能主要集中在:

  • 用于数据整理和清理、子集构造和过滤、转换等快速的矢量化数组运算
  • 常用的数组算法,如排序、唯一化、集合运算等
  • 高效的描述统计和数据聚合/摘要运算
  • 用于异构数据集的合并/连接运算的数据对⻬和关系型数据运算
  • 将条件逻辑表述为数组表达式(而不是带有if-elif-else分⽀的循环)
  • 数据的分组运算(聚合、转换、函数应用等)

虽然NumPy提供了通用的数值数据处理的计算基础,但大多数读者可能还是想将pandas作为统计和分析工作的基础,尤其是处理表格数据时。pandas还提供了一些NumPy所没有的更加领域特定的功能,如时间序列处理等。

Python的面向数组计算可以追溯到1995年,JimHugunin创建了Numeric库。接下来的10年,许多科学编程社区纷纷开始使用Python的数组编程,但是进入21世纪,库的生态系统变得碎片化了。2005年,Travis Oliphant从Numeric和Numarray项目整了出了NumPy项目,进而所有社区都集合到了这个框架下。

NumPy之于数值计算特别重要的原因之一,是因为它可以高效处理大数组的数据。这是因为:

  • NumPy是在一个连续的内存块中存储数据,独立于其他Python内置对象。NumPy的C语言编写的算法库可以操作内存,而不必进行类型检查或其它前期工作。比起Python的内置序列,NumPy数组使用的内存更少。
  • NumPy可以在整个数组上执行复杂的计算,而不需要Python的for循环

2.1、NumPy的ndarray:一种多维数组对象

NumPy最重要的一个特点就是其N维数组对象(即ndarray),该对象是一个快速而灵活的大数据集容器。你可以利用这种数组对整块数据执行一些数学运算,其语法跟标量元素之间的运算一样。

要明⽩Python是如何利用与标量值类似的语法进行批次计算,我们先引入NumPy,然后生成一个包含随机数据的小数组:

import numpy as np

data = np.random.randn(2,3)

data

data*10

data+data

然后进行数学运算:

98b14427223245b48d34c11cb807f6bb.png

第一个例子中,所有的元素都乘以10。第二个例子中,每个元素都与自身相加。

ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数组都有一个shape(一个表示各维度大小的元组)和一个dtype(一个用于说明数组数据类型的对象):

data.shape
(2, 3)
data.dtype
dtype('float64')

本章将会介绍NumPy数组的基本用法,这对于本书后面各章的理解基本够用。虽然大多数数据分析工作不需要深入理解NumPy,但是精通面向数组的编程和思维方式是成为Python科学计算⽜⼈的一大关键步骤。

2.1.1 创建ndarray

创建数组最简单的办法就是使用array函数。它接受一切序列型的对象(包括其他数组),然后产生一个新的含有传入数据的NumPy数组。以一个列表的转换为例:

data1 = [6,7.5,8,0.5]
arr1 = np.array(data1)

arr1

array([ 6. , 7.5, 8. , 0. , 1. ])

嵌套序列(比如由一组等长列表组成的列表)将会被转换为一个多维数组:

data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
arr2 = np.array(data2)
arr2
array([[1, 2, 3, 4],
[5, 6, 7, 8]])

因为data2是列表的列表,NumPy数组arr2的两个维度的shape是从data2引入的。可以用属性ndim和shape验证:

In [25]:   arr2.ndim
Out[25]: 2
In [26]:   arr2.shape
Out[26]: (2, 4)

除非特别说明(稍后将会详细介绍),np.array会尝试为新建的这个数组推断出一个较为合适的数据类型。数据类型保存在一个特殊的dtype对象中。比如说,在上面的两个例子中,我们有:

dtype('float64')

除np.array之外,还有一些函数也可以新建数组。比如,zerosones分别可以创建指定长度或形状的全0或全1数组。empty可以创建一个没有任何具体值的数组。要用这些方法创建多维数组,只需传入一个表示形状的元组即可:

np.zeros(10)
np.zeros((3, 6))
np.empty((2, 3, 2))

f0c1b8d81bde407d9755d184111031d7.png

5a762b9e449049149e41597d76e25d77.png

a02c8b6d50a543f9ac66106560cd47a9.png

注意:认为np.empty会返回全0数组的想法是不安全的。很多情况下(如前所示),它返回的都是一些未初始化的垃圾值。

下表列出了一些数组创建函数。由于NumPy关注的是数值计算,因此,如果没有特别指定,数据类型基本都是float64(浮点数)。

9e365a8cccbe4bc39444558f50ba10e6.png

2.1.2 ndarray的数据类型

dtype(数据类型)是一个特殊的对象,它含有ndarray将一块内存解释为特定数据类型所需的信息:

In    [33]: arr1 = np.array([1, 2, 3], dtype=np.float64)
In    [34]: arr2 = np.array([1, 2, 3], dtype=np.int32)
In    [35]: arr1.dtype
Out [35]: dtype('float64')
In    [36]: arr2.dtype
Out [36]: dtype('int32')

dtype是NumPy灵活交互其它系统的源泉之一。多数情况下,它们直接映射到相应的机器表示,这使得“读写磁盘上的二进制数据流”以及“集成低级语言代码(如C、Fortran)”等工作变得更加简单。数值型dtype的命名方式相同:一个类型名(如float或int),后面跟一个用于表示各元素位长的数字。标准的双精度浮点值(即Python中的float对象)需要占用8字节(即64位)。因此,该类型在NumPy中就记作float64。下表列出了NumPy所⽀
持的全部数据类型。

a0fb4a2eca6d440f9a883267af05814e.png

你可以通过ndarray的astype方法明确地将一个数组从一个dtype转换成另一个dtype:

arr = np.array([1, 2, 3, 4, 5])
float_arr = arr.astype(np.float64)

2.1.3 NumPy数组的运算

数组很重要,因为它使你不用编写循环即可对数据执行批量运算。NumPy用户称其为矢量化vectorization)。大小相等的数组之间的任何算术运算都会将运算应用到元素级:

import numpy as np
arr = np.array([[1., 2., 3.], [4., 5., 6.]])

arr

d70444488811435fa02518b1edb742cd.png

arr * arr

1bb5afca1c1c460e9fa7bd70c52b5765.png
大小相同的数组之间的比较会生成布尔值数组:

import numpy as np
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])

arr>arr2

da8bcb2b589640a1a1e3b6a074adc287.png

2.1.4 基本的索引和切片

NumPy数组的索引是一个内容丰富的主题,因为选取数据子集或单个元素的方式有很多。一维数组很简单。从表面上看,它们跟Python列表的功能差不多:

arr = np.arange(10)
arr[5:8]

a97bf66268ed470596c97f2cf60dccb0.png

arr[5:8] = 12
arr[5:8]

4a3f1994c4734b1dbcb233b1b0147099.png

如上所示,当你将一个标量值赋值给一个切片时(如arr[5:8]=12),该值会自动传播(也就说后面将会讲到的“广播”)到整个选区。跟列表最重要的区别在于,数组切片是原始数组的视图(相当于java中的引用)。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上

作为例子,先创建一个arr的切片:

arr_slice = arr[5:8]
arr_slice

863c7595793245f2981fbd0f938949e8.png

现在,当我修稿arr_slice中的值,变动也会体现在原始数组arr中:

arr_slice[1] = 12345
arr

8f96afab76684c26ad16fe2f36af1b32.png

切片[ : ]会给数组中的所有值赋值:

arr_slice[:] = 64

7471336b4ce247849e67bedbee6ded8f.png

如果你刚开始接触NumPy,可能会对此感到惊讶(尤其是当你曾经用过其他热衷于复制数组数据的编程语言)。由于NumPy的设计目的是处理大数据,所以你可以想象一下,假如NumPy坚持要将数据复制来复制去的话会产生何等的性能和内存问题。

注意:如果你想要得到的是ndarray切片的一份副本而非视图,就需要明确地进行复制操作,例如arr[5:8].copy()。

在多维数组中,如果省略了后面的索引,则返回对象会是一个维度低一点的ndarray(它含有高一级维度上的所有数据)。因此,在2×2×3数组arr3d中:

arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7,8,9],[10,11,12]]])

arr3d

716815781bd04dc6a687761ae331681d.png

arr3d[0]是一个2×3数组:

ac008279b22e46cda1f8f917f94b7f94.png

标量值和数组都可以被赋值给arr3d[0]:

old_values = arr3d[0].copy()
arr3d[0] = 42

arr3d

fe468afb7e554d5c8f1516278a5fbfc9.png

arr3d[0] = old_values
arr3d

6c398b31a45b4853bf53e8f9d68d1e51.png

2.1.5 切片索引

ndarray的切片语法跟Python列表这样的一维对象差不多,对于之前的二维数组arr2d,其切片方式稍显不同:

arr2d=([[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])

arr2d

d7e7492425144f6dbb5ce8c7f0e871f8.png

f7ece926d83349878ac8c670efcdbdc7.png

可以看出,它是沿着第0轴(即第一个轴)切片的。也就是说,切片是沿着一个轴向选取元素的。表达式arr2d[:2]可以被认为是“选取arr2d的前两行”。

你可以一次传入多个切片,就像传入多个索引那样:

arr2d=np.array([[1, 2, 3],
        [4, 5, 6],
        [4, 9, 6],
        [7, 8, 9]])
arr2d[1, :2]

d20ef08122ec4c38b5f885d98f1874f1.png

像这样进行切片时,只能得到相同维数的数组视图。通过将整数索引和切片混合,可以得到低维度的切片。

例如,我可以选取第二行的前两列:

eec9222fba3844c8ae284f4271330e2d.png
相似的,还可以选择第三列的前两行:

eefca17183494d4388b338dce20df8c2.png

注意,“只有冒号”表示选取整个轴,因此你可以像下面这样只对高维轴进行切片:
95e0ddd0fdae4ac387734aecd40c1c2e.png

8677a602b9574108a0f75f0ecd6aa155.png

自然,对切片表达式的赋值操作也会被扩散到整个选区。

2.1.6 布尔型索引

来看这样一个例子,假设我们有一个用于存储数据的数组以及一个存储姓名的数组(含有重复项)。在这⾥,我将使用numpy.random中的randn函数生成一些正态分布的随机数据:

names = np.array(['Bob', 'Joe', 'Will', 'Bob','Will','Joe'])
data = np.random.randn(7, 4)

names

71a8a78f377344f38a31a8a204be5051.png

假设每个名字都对应data数组中的一行,而我们想要选出对应于名字"Bob"的所有行。跟算术运算一样,数组的比较运算(如==)也是矢量化的。因此,对names和字符串"Bob"的比较运算将会产生一个布尔型数组:

024ee96a0ff443d9a9c2188176e40a47.png

这个布尔型数组可用于数组索引:

b335253fb17840458d9e03abc7cab76c.png

布尔型数组的长度必须跟被索引的轴长度一致。此外,还可以将布尔型数组跟切片、整数(或整数序列)混合使用.

通过布尔型数组设置值是一种经常用到的手段。为了将data中的所有负值都设置为0,我们只需:

data[data < 0] = 0

2.1.7 花式索引

花式索引(Fancy indexing)是一个NumPy术语,它指的是利用整数数组进行索引。假设我们有一个8×4数组:

arr = np.empty((8, 4))
for i in range(8):
    arr[i] = i

arr

699e726c533f455b9a12b9a3022c3510.png

为了以特定顺序选取行子集,只需传⼊一个用于指定顺序的整数列表或ndarray即可:

1d8606def94944058b4a9c68a25686aa.png

这段代码确实达到我们的要求了!使用负数索引将会从末尾开始选取行。一次传⼊多个索引数组会有一点特别。它返回的是一个一维数组,其中的元素对应各个索引元组:

arr = np.arange(32).reshape((8, 4))
arr

b177239a322f42d98cbee2625d7eab6a.png

最终选出的是元素(1,0)、(5,3)、(7,1)和(2,2)。⽆论数组是多少维的,花式索引总是一维的。这个花式索引的行为可能会跟某些用户的预期不一样(包括我在内),选取矩阵的行列子集应该是矩形区域的形式才对。下面是
得到该结果的一个办法:

dcce6cbe745e4e93a696b3cdaa7d16e6.png

记住,花式索引跟切片不一样,它总是将数据复制到新数组中。

2.1.8 数组转置和轴对换

转置是重塑的一种特殊形式,它返回的是源数据的视图(不会进行任何复制操作)。数组不仅有transpose方法,还有一个特殊的T属性:

arr = np.arange(15).reshape((3, 5))
arr

0683b2bcc0644dc9823576626a8ab400.png

b8dd112569ea40149710adf6b336f244.png

在进行矩阵计算时,经常需要用到该操作。

对于⾼维数组,transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置(比较费脑子):

arr = np.arange(16).reshape((2, 2, 4))
arr

27031b3636484ef19e3d7ba930d51912.png

e58e030edd2a4ef18eb25410ed977b7f.png

这⾥,第一个轴被换成了第二个,第二个轴被换成了第一个,最后一个轴不变。

简单的转置可以使用.T,它其实就是进行轴对换而已。ndarray还有一个swapaxes方法,它需要接受一对轴编号:

675b9e25c8014a8280dbcf537c10dfd0.png

swapaxes也是返回源数据的视图(不会进行任何复制操作)。

2.2 通用函数:快速的元素级数组函数

通用函数(即ufunc)是一种对ndarray中的数据执行元素级运算的函数。你可以将其看做简单函数(接受一个或多个标量值,并产生一个或多个标量值)的矢量化包装器。

许多ufunc都是简单的元素级变体,如sqrt和exp:

arr = np.arange(10)
arr

08136571f9d2418392acb8ca28b64901.png

np.sqrt(arr)

7963bb880b454846894325fe962d5a5e.png

这些都是一元(unary)ufunc。另外一些(如add或maximum)接受2个数组(因此也叫二元(binary)ufunc),并返回一个结果数组:

x = np.random.randn(8)
y = np.random.randn(8)
np.maximum(x, y)

bbfc06c27b3949d5847ab967aeaa0520.png

下图给出了一些一元和二元ufunc:

a1b6309f96c346708fc6e7d7f3371336.png

685aac69bdc64b1a9e386db44897312a.png

65e720580171479698fd0669c43db9bc.png

33d96d5207a049aba4e3bf6cdb97d4ba.png

48fdf0a7da464daf992ea789021f69e8.png

2.3 利用数组进行数据处理

NumPy数组使你可以将许多种数据处理任务表述为简洁的数组表达式(否则需要编写循环)。用数组表达式代替循环的做法,通常被称为矢量化。一般来说,矢量化数组运算要比等价的纯Python方式快上一两个数量级(甚至更多),尤其是各种数值计算。在后面内容中我将介绍广播,这是一种针对矢量化计算的强大手段。

作为简单的例子,假设我们想要在一组值(网格型)上计算函数sqrt(x2 + y2)。np.meshgrid函数接受两个一维数组,并产生两个二维矩阵(对应于两个数组中所有的(x,y)对):

# 从-5开始,到5,步长为0.01,生成数据
points = np.arange(-5, 5, 0.01)
xs, ys = np.meshgrid(points, points)
ys

360fa9abaeaf41d8aaec735a1e124f0b.png

现在,对该函数的求值运算就好办了,把这两个数组当做两个浮点数那样编写表达式即可:

z = np.sqrt(xs ** 2 + ys ** 2)
z

f32828751b0b43b6981860760882d0f2.png

对于z的分布,如下:

import matplotlib.pyplot as plt
plt.imshow(z)
plt.colorbar()
plt.title("Image plot of $\sqrt{x^2 + y^2}$ for grid of values")

aab1c7efd31b4e51b1fdf82be4dfe913.png

2.3.1 将条件逻辑表述为数组运算

numpy.where函数是三元表达式x if condition else y的矢量化版本。假设我们有一个布尔数组和两个值数组:

xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])

假设我们想要根据cond中的值选取xarr和yarr的值:当cond中的值为True时,选取xarr的值,否则从yarr中选取。列表推导式的写法应该如下所示:

result = [(x if c else y)
          for x, y, c in zip(xarr, yarr, cond)]

result

这有几个问题。第一,它对大数组的处理速度不是很快(因为所有工作都是由纯Python完成的)。第二,⽆法用于多维数组。若使用np.where,则可以将该功能写得非常简洁:

result = np.where(cond, xarr, yarr)
result

np.where的第二个和第三个参数不必是数组,它们都可以是标量值。在数据分析工作中,where通常用于根据另一个数组而产生一个新的数组。假设有一个由随机数据组成的矩阵,你希望将所有正值替换为2,将所有负值替换为-2。若利用np.where,则会非常简单:

arr = np.random.randn(4, 4)
arr
tmp = np.where(arr > 0,2,-1)
tmp

a13c2a4938bb412d96309d83a6cd52c4.png

使用np.where,可以将标量和数组结合起来。例如,我可用常数2替换arr中所有正的值:

np.where(arr > 0, 2, arr)

cf45ad95ccb748d0a6fa33b658c010ec.png

传递给where的数组大小可以不相等,甚至可以是标量值。

2.3.2 数学和统计方法

可以通过数组上的一组数学函数对整个数组或某个轴向的数据进行统计计算。sum、mean以及标准差std等聚合计算(aggregation,通常叫做约简(reduction))既可以当做数组的实例方法调用,也可以当做顶级NumPy函数使用。

这⾥,我生成了一些正态分布随机数据,然后做了聚类统计:

arr = np.random.randn(5, 4)

np.mean(arr) # 0.06813175672246549
np.sum(arr) # 1.36263513444931

mean和sum这类的函数可以接受一个axis选项参数,用于计算该轴向上的统计值,最终结果是一个少一维的数组:

arr.mean(axis=1)

499afaac683c41928dc19d6a0f0ae886.png

arr.sum(axis=0)

de7333184e75450d919dcc6855aa98b5.png

这⾥,arr.mean(1)是“计算行的平均值”,arr.sum(0)是“计算每列的和”。

其他如cumsum和cumprod之类的方法则不聚合,而是产生一个由中间结果组成的数组;在多维数组中,累加函数(如cumsum)返回的是同样大小的数组,但是会根据每个低维的切片沿着标记轴计算部分聚类。

下图列出了全部的基本数组统计方法。后续章节中有很多例子都会用到这些方法:

f7831d34c5814b2faf6ca6306b0da920.png

c4744822cbb74338a1699a431d55bce2.png

2.3.2 用于布尔型数组的方法

在上面这些方法中,布尔值会被强制转换为1(True)和0(False)。因此,sum经常被用来对布尔型数组中的True值计数:

arr = np.random.randn(100)
# arr
(arr > 0).sum() # 46

另外还有两个方法any和all,它们对布尔型数组非常有用。any用于测试数组中是否存在一个或多个True,而all则检查数组中所有值是否都是True:

bools = np.array([False, False, True, False, False])

bools.any() # True

bools.all() # False

这两个方法也能用于非布尔型数组,所有非0元素将会被当做True;

2.3.3 排序

跟Python内置的列表类型一样,NumPy数组也可以通过sort方法就地排序:

arr = np.random.randn(6)
arr.sort()

多维数组可以在任何一个轴向上进行排序,只需将轴编号传给sort即可:

arr.sort(1)
arr

顶级方法np.sort返回的是数组的已排序副本,而就地排序则会修改数组本身。计算数组分位数最简单的办法是对其进行排序,然后选取特定位置的值。

2.3.4 唯一化以及其它的集合逻辑

NumPy提供了一些针对一维ndarray的基本集合运算。最常用的可能要数np.unique了,它用于找出数组中的唯一值并返回已排序的结果:

names = np.array(['Bob', 'Joe', 'Will', 'Bob','Will','Joe','Will'])
np.unique(names)

57ba05021d724b94b2f7d8829a2d3fbb.png

更多的集合运算如下:

e3e7d6956bf441baa825ecb66d4e11b5.png

2.4 用于数组的文件输⼊输出

NumPy能够读写磁盘上的文本数据或二进制数据。这一小节只讨论NumPy的内置二进制格式。

np.save和np.load是读写磁盘数组数据的两个主要函数。默认情况下,数组是以未压缩的原始二进制格式保存在扩展名为.npy的文件中的:

arr = np.arange(10)
np.save('some_array', arr)

如果文件路径末尾没有扩展名.npy,则该扩展名会被自动加上。然后就可以通过np.load读取磁盘上的数组:

np.load('some_array.npy')

通过np.savez可以将多个数组保存到一个未压缩文件中,将数组以关键字参数的形式传⼊即可:

np.savez('array_archive.npz', a=arr, b=arr)

加载.npz文件时,你会得到一个类似字典的对象,该对象会对各个数组进行延迟加载:

arch = np.load('array_archive.npz')
arch['b']

2.5 线性代数

线性代数(如矩阵乘法、矩阵分解、行列式以及其他方阵数学等)是任何数组库的重要组成部分。不像某些语言(如MATLAB),通过*对两个二维数组相乘得到的是一个元素级的积,而不是一个矩阵点积。因此,NumPy提供了一个用于矩阵乘法的dot函数(既是一个数组方法也是numpy命名空间中的一个函数):

x = np.array([[1., 2., 3.], [4., 5., 6.]])
y = np.array([[6., 23.], [-1, 7], [8, 9]])
x.dot(y) # np.dot(x, y)

42d62153222946d184e7f2a5b95d35f8.png

一个二维数组跟一个大小合适的一维数组的矩阵点积运算之后将会得到一个一维数组:

np.dot(x, np.ones(3))

f9711c72d9184497af833d71923ebe1e.png

@符(类似Python 3.5)也可以用作中缀运算符,进行矩阵乘法:

x @ np.ones(3)

8e09809934e945eebccccda8920c179b.png

numpy.linalg中有一组标准的矩阵分解运算以及诸如求逆和行列式之类的东⻄。它们跟MATLAB和R等语言所使用的是相同的行业标准线性代数库,如BLAS、LAPACK、Intel MKL(MathKernel Library,可能有,取决于你的NumPy版本)等:

from numpy.linalg import inv, qr
X = np.random.randn(5, 5)
mat = X.T.dot(X)
inv(mat) #

859e0836e5644b02857265c4ed401b5f.png

表达式X.T.dot(X)计算X和它的转置X.T的点积。

下表列出了一些最常用的线性代数函数:

df56152b33cf43a280b682d6319757e2.png

2.6 伪随机数生成

numpy.random模块对Python内置的random进行了补充,增加了一些用于⾼效生成多种概率分布的样本值的函数。例如,你可以用normal来得到一个标准正态分布的4×4样本数组:

samples = np.random.normal(size=(4, 4))
samples

e88c3029d517449786af5a11ab1b7f9e.png

我们说这些都是伪随机数,是因为它们都是通过算法基于随机数生成器种子,在确定性的条件下生成的。你可以用NumPy的np.random.seed更改随机数生成种子:np.random.seed(1234)

numpy.random的数据生成函数使用了全局的随机种子。要避免全局状态,你可以使用numpy.random.RandomState,创建一个与其它隔离的随机数生成器:rng = np.random.RandomState(1234)

下表列出了numpy.random中的部分函数:

b687108f289146c6af044bc013511e9e.png

d01fc85666a940b7b778b9fde0f4c484.png

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

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

相关文章

SuiNS更新命名标准,增强用户体验

SuiNS将其面向用户的命名标准从 xxx.sui 更新为 xxx&#xff0c;让用户能够以一种适用于Web2和Web3世界的方式来代表自己。通过此更新&#xff0c;用户可以在其选择的名称前使用 &#xff0c;而不是在名称后添加 .sui。 Sui命名服务于去年推出&#xff0c;旨在使Sui上的地址更…

docker-compose harbor 2.11

harbor 前言 “Harbor” 是一个用于管理容器镜像的开源仓库项目。由 VMware 开发和维护,Harbor 提供一个企业级的 Docker 镜像仓库,具有丰富的功能,包括: 镜像管理:提供存储和分发 Docker 镜像的能力。安全性:支持镜像签名和漏洞扫描,确保镜像的安全性。身份认证:集成…

python-开学?

[题目描述] 小执&#xff1a;终于可以开学啦&#xff01;好开心啊&#xff01; 小理&#xff1a;你没看新闻吗&#xff0c;开学日期又延后了。 小执&#xff1a;&#x1d441;&#x1d442;&#x1d442;&#x1d442;&#x1d442;&#x1d442;&#x1d442;&#x1d442;&am…

一文梳理ChatTTS的进阶用法,手把手带你实现个性化配音,音色、语速、停顿,口语,全搞定

前几天和大家分享了如何从0到1搭建一套语音交互系统。 其中&#xff0c;语音合成&#xff08;TTS&#xff09;是提升用户体验的关键所在。于是&#xff0c;上一篇接着和大家聊了聊&#xff1a;全网爆火的AI语音合成工具-ChatTTS&#xff0c;有人已经拿它赚到了第一桶金&#x…

代理配置SQUID

目录 SQUID代理服务器配置 监听浏览器访问记录 拒绝访问配置 SQUID代理服务器配置 实验系统 windows 10 xxxxx Roucky_linux9.4 192.168.226.22 监听浏览器访问记录 1. 安装squid yum install squid -y 2. 编辑squid配置文件 vim /etc/squid…

等保一体机:多种防护机制,让等保合规简单高效!

自1994年国务院颁布《中华人民共和国计算机信息系统安全保护条例》规定计算机信息系统实行安全等级保护以来&#xff0c;等级保护工作经过了近25年的发展历程&#xff0c;成为了我国网络安全保护的重要举措之一。 2019年12月1日等保2.0正式开始实施&#xff0c;我国网络安全行业…

【大分享05】动态容差归档,打通不动产登记管理“最后一公里”

关注我们 - 数字罗塞塔计划 - 本篇是参加由电子文件管理推进联盟联合数字罗塞塔计划发起的“大分享”活动投稿文章&#xff0c;来自上海涵妍档案信息技术有限责任公司&#xff0c;作者&#xff1a;陈雪。 一、政策背景 在“互联网政务服务”的浪潮下&#xff0c;各级政府机构…

在低侧电流检测中使用单端放大器:误差源和布局技巧

低侧检测的主要优点是可以使用相对简单的配置来放大分流电阻器两端的电压。例如&#xff0c;通用运算放大器的同相配置可能是需要能够在消费市场领域竞争的成本敏感型电机控制应用的有效选择。 基于同相配置的电路图如图1所示。 图1。 然而&#xff0c;这种低成本解决方案可能…

2288. 价格减免

题目 给定一个字符串列表 sentence&#xff0c;表示一个句子&#xff0c;其中每个单词可以包含数字、小写字母和美元符号 $。如果单词的形式为美元符号后跟着一个非负实数&#xff0c;那么这个单词就表示一个价格。我们需要在价格的基础上减免给定的 discount%&#xff0c;并更…

2023数A题——WLAN网络信道接入机制建模

A题——WLAN网络信道接入机制建模 思路&#xff1a;该题主要考察的WLAN下退避机制建模仿真。 资料获取 问题1&#xff1a; 假设AP发送包的载荷长度为1500Bytes&#xff08;1Bytes 8bits&#xff09;&#xff0c;PHY头时长为13.6μs&#xff0c;MAC头为30Bytes&#xff0c;MA…

上海科技博物馆超薄OLED柔性壁纸屏应用方案

产品&#xff1a;2组55寸OLED柔性屏2x1 特点&#xff1a;嵌入墙体&#xff0c;与空间装饰融入一体 用途&#xff1a;播放文物展示 一、项目背景 上海科技博物馆作为展示科技与文化的交汇点&#xff0c;一直致力于为观众提供沉浸式的参观体验。为了提升文物展示的现代化和科技感…

不可忽视的9条网页排版设计规则,你了解吗?

网页设计由95%的排版组成。网页排版设计使图形的放置栩栩如生&#xff0c;让用户保持愉悦&#xff0c;容易被用户视觉感知。在这个过程中&#xff0c;网页排版设计需要考虑很多因素:款式、大小、字体颜色等。此外&#xff0c;设计师通过网页排版&#xff0c;让文字增加设计的美…

Kafka 高性能 7 大秘诀之 Segment 消息存储机制的奥妙

《Kafka 高性能 7 大秘诀》第 4 篇&#xff0c;解密 kafka Segment 日志存储思想哲学以及如何将磁盘的随机读写变成顺序读写&#xff0c;提高磁盘读写速度。 Kafka 使用日志文件存储消息&#xff0c;每个 Partition 的消息被存储在多个 Segment 文件中&#xff0c;避免了单个文…

经典神经网络(11)VQ-VAE模型及其在MNIST数据集上的应用

经典神经网络(11)VQ-VAE模型及其在MNIST数据集上的应用 我们之前已经了解了PixelCNN模型。 经典神经网络(10)PixelCNN模型、Gated PixelCNN模型及其在MNIST数据集上的应用 今天&#xff0c;我们了解下DeepMind在2017年提出的一种基于离散隐变量&#xff08;Discrete Latent va…

OneNote 作为恶意软件分发新渠道持续增长

目前&#xff0c;Office 文件已经默认禁用宏代码&#xff0c;攻击者开始转向利用其他微软的软件产品来进行恶意 Payload 投递。默认情况下&#xff0c;OneNote 应用也包含在 Office 2019 和 Microsoft 365 软件中&#xff0c;所以 OneNote 文件越来越受到攻击者的青睐。如果有人…

调度算法-内存页面置换算法

缺⻚异常&#xff08;缺⻚中断&#xff09; 与⼀般中断的主要区别在于&#xff1a; 缺⻚中断在指令执⾏「期间」产⽣和处理中断信号&#xff0c;⽽⼀般中断在⼀条指令执⾏「完成」后检查和处理中断信号。缺⻚中断返回到该指令的开始重新执⾏「该指令」&#xff0c;⽽⼀般中断返…

如何完美解决 Oracle Database 19c 安装程序 - 第7步(共8步)卡住,半小时都不动

&#x1f680; 如何完美解决 Oracle Database 19c 安装程序 - 第7步&#xff08;共8步&#xff09;卡住&#xff0c;半小时都不动 摘要 在安装 Oracle Database 19c 时&#xff0c;很多用户会在第7步&#xff08;共8步&#xff09;遇到卡住的问题&#xff0c;尤其是安装程序长…

ESP32蓝牙串口通讯

文章目录 一、前言二、代码三、运行 一、前言 ESP32支持经典蓝牙和低功耗蓝牙&#xff08;BLE&#xff09;,经典蓝牙可在计算机上模拟出一个串口&#xff0c;使得ESP32可以以串口的方式和计算机通信。 二、代码 #include "BluetoothSerial.h"String device_name …

Upload-Labs-Linux1 使用 一句话木马

解题步骤&#xff1a; 1.新建一个php文件&#xff0c;编写内容&#xff1a; <?php eval($_REQUEST[123]) ?> 2.将编写好的php文件上传&#xff0c;但是发现被阻止&#xff0c;网站只能上传图片文件。 3.解决方法&#xff1a; 将php文件改为图片文件&#xff08;例…