Geeks_Z の Blog Geeks_Z の Blog
首页
  • 学习笔记

    • 《HTML》
    • 《CSS》
    • 《JavaWeb》
    • 《Vue》
  • 后端文章

    • Linux
    • Maven
    • 汇编语言
    • 软件工程
    • 计算机网络概述
    • Conda
    • Pip
    • Shell
    • SSH
    • Mac快捷键
    • Zotero
  • 学习笔记

    • 《数据结构与算法》
    • 《算法设计与分析》
    • 《Spring》
    • 《SpringMVC》
    • 《SpringBoot》
    • 《SpringCloud》
    • 《Nginx》
  • 深度学习文章
  • 学习笔记

    • 《PyTorch》
    • 《ReinforementLearning》
    • 《MetaLearning》
  • 学习笔记

    • 《高等数学》
    • 《线性代数》
    • 《概率论与数理统计》
  • 增量学习
  • 哈希学习
GitHub (opens new window)

Geeks_Z

AI小学生
首页
  • 学习笔记

    • 《HTML》
    • 《CSS》
    • 《JavaWeb》
    • 《Vue》
  • 后端文章

    • Linux
    • Maven
    • 汇编语言
    • 软件工程
    • 计算机网络概述
    • Conda
    • Pip
    • Shell
    • SSH
    • Mac快捷键
    • Zotero
  • 学习笔记

    • 《数据结构与算法》
    • 《算法设计与分析》
    • 《Spring》
    • 《SpringMVC》
    • 《SpringBoot》
    • 《SpringCloud》
    • 《Nginx》
  • 深度学习文章
  • 学习笔记

    • 《PyTorch》
    • 《ReinforementLearning》
    • 《MetaLearning》
  • 学习笔记

    • 《高等数学》
    • 《线性代数》
    • 《概率论与数理统计》
  • 增量学习
  • 哈希学习
GitHub (opens new window)
  • Python

    • 语法基础

    • 数据结构 函数 和文件

    • 进阶

    • NumPy

      • Numpy基础
      • ndarray
      • 通用函数
      • NumPy 基础:数组和向量计算
      • 文件输入输出
      • 线性代数
      • 伪随机数生成
      • 其他
        • 示例:随机漫步
          • 一次模拟多个随机漫步
        • 补充
          • genfromtxt
  • MLTutorials

  • 卷积神经网络

  • 循环神经网络

  • Transformer

  • VisionTransformer

  • 扩散模型

  • 计算机视觉

  • PTM

  • MoE

  • LoRAMoE

  • LongTailed

  • 多模态

  • 知识蒸馏

  • PEFT

  • 对比学习

  • 小样本学习

  • 迁移学习

  • 零样本学习

  • 集成学习

  • Mamba

  • PyTorch

  • CL

  • CIL

  • 小样本类增量学习FSCIL

  • UCIL

  • 多模态增量学习MMCL

  • LTCIL

  • DIL

  • 论文阅读与写作

  • 分布外检测

  • GPU

  • 深度学习调参指南

  • AINotes
  • Python
  • NumPy
Geeks_Z
2024-12-15
目录

其他

示例:随机漫步

我们通过模拟随机漫步来说明如何运用数组运算。先来看一个简单的随机漫步的例子:从 0 开始,步长 1 和 -1 出现的概率相等。

下面是一个通过内置的random模块以纯 Python 的方式实现 1000 步的随机漫步:

In [247]: import random
   .....: position = 0
   .....: walk = [position]
   .....: steps = 1000
   .....: for i in range(steps):
   .....:     step = 1 if random.randint(0, 1) else -1
   .....:     position += step
   .....:     walk.append(position)
   .....:
1
2
3
4
5
6
7
8
9

图 4-4 是根据前 100 个随机漫步值生成的折线图:

In [249]: plt.plot(walk[:100])
1
图 4-4 简单的随机漫步

不难看出,这其实就是随机漫步中各步的累计和,可以用一个数组运算来实现。因此,我用np.random模块一次性随机产生 1000 个“掷硬币”结果(即两个数中任选一个),将其分别设置为 1 或 -1,然后计算累计和:

In [251]: nsteps = 1000

In [252]: draws = np.random.randint(0, 2, size=nsteps)

In [253]: steps = np.where(draws > 0, 1, -1)

In [254]: walk = steps.cumsum()
1
2
3
4
5
6
7

有了这些数据之后,我们就可以沿着漫步路径做一些统计工作了,比如求取最大值和最小值:

In [255]: walk.min()
Out[255]: -3

In [256]: walk.max()
Out[256]: 31
1
2
3
4
5

现在来看一个复杂点的统计任务——首次穿越时间,即随机漫步过程中第一次到达某个特定值的时间。假设我们想要知道本次随机漫步需要多久才能距离初始 0 点至少 10 步远(任一方向均可)。np.abs(walk)>=10可以得到一个布尔型数组,它表示的是距离是否达到或超过 10,而我们想要知道的是第一个 10 或 -10 的索引。可以用argmax来解决这个问题,它返回的是该布尔型数组第一个最大值的索引(True就是最大值):

In [257]: (np.abs(walk) >= 10).argmax()
Out[257]: 37
1
2

注意,这里使用argmax并不是很高效,因为它无论如何都会对数组进行完全扫描。在本例中,只要发现了一个True,那我们就知道它是个最大值了。

一次模拟多个随机漫步

如果你希望模拟多个随机漫步过程(比如 5000 个),只需对上面的代码做一点点修改即可生成所有的随机漫步过程。只要给numpy.random的函数传入一个二元元组就可以产生一个二维数组,然后我们就可以一次性计算 5000 个随机漫步过程(一行一个)的累计和了:

In [258]: nwalks = 5000

In [259]: nsteps = 1000

In [260]: draws = np.random.randint(0, 2, size=(nwalks, nsteps)) # 0 or 1

In [261]: steps = np.where(draws > 0, 1, -1)

In [262]: walks = steps.cumsum(1)

In [263]: walks
Out[263]: 
array([[  1,   0,   1, ...,   8,   7,   8],
       [  1,   0,  -1, ...,  34,  33,  32],
       [  1,   0,  -1, ...,   4,   5,   4],
       ..., 
       [  1,   2,   1, ...,  24,  25,  26],
       [  1,   2,   3, ...,  14,  13,  14],
       [ -1,  -2,  -3, ..., -24, -23, -22]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

现在,我们来计算所有随机漫步过程的最大值和最小值:

In [264]: walks.max()
Out[264]: 138

In [265]: walks.min()
Out[265]: -133
1
2
3
4
5

得到这些数据之后,我们来计算 30 或 -30 的最小穿越时间。这里稍微复杂些,因为不是 5000 个过程都到达了 30。我们可以用any方法来对此进行检查:

In [266]: hits30 = (np.abs(walks) >= 30).any(1)

In [267]: hits30
Out[267]: array([False,  True, False, ..., False,  True, False], dtype=bool)

In [268]: hits30.sum() # Number that hit 30 or -30
Out[268]: 3410
1
2
3
4
5
6
7

然后我们利用这个布尔型数组选出那些穿越了 30(绝对值)的随机漫步(行),并调用argmax在轴 1 上获取穿越时间:

In [269]: crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1)

In [270]: crossing_times.mean()
Out[270]: 498.88973607038122
1
2
3
4

请尝试用其他分布方式得到漫步数据。只需使用不同的随机数生成函数即可,如normal用于生成指定均值和标准差的正态分布数据:

In [271]: steps = np.random.normal(loc=0, scale=0.25,
   .....:                          size=(nwalks, nsteps))
1
2

补充

genfromtxt

Numpy 中导入数据方式有多种,其中函数之一为 genfromtxt ,genformtxt 相对其他函数有自己的优势和劣势,

  • 劣势:相对其它函数数据加载慢,从数据读入到返回需要两个迭代循环,第一个迭代将文件中每一行转化为一个字符串序列,第二个循环迭代对每个字符串序列指定合适的数据类型;源于这两个迭代原因,相对其它函数会慢一点;
  • 优势:更灵活,数据加载时会能够处理丢失数据,例如对某些 missing_values 做一些数据填充,或将某一列数据从一中形式转化为另一种形式;

函数语法如下:

**genfromtxt(fname,dtype,comments,delimiter,skipd_header,skip_fonter,converters,missing_values,filling_values,usecols,names, autostrip,kwarg)

  • fname -> str/list /IO Object 等等,表示数据源;文件路径,字符串列表、StringIO 对象都可;
  • dtype -> dtype,最终数组的数据类型;
  • comments -> str,注释标识符,加载时会自动忽略位于注释标识符后面的字符串;
  • delimiter -> str/int/sequence,分割符,加载时来分割字符串,比较常见的就是逗号,也可以指定 int 整形表示每一个元素最大宽度;也可以是字符列表,表示分割符可为多个字符;
  • skip_header -> int,数据加载时跳过文件头部的字符行数;
  • skip_footer -> int,数据加载时跳过文件尾部字符串行数;
  • converters -> variable,可以是字典形式也可以是 lambda 函数,表示将某一种数据格式转化为另一种数据格式;
  • missing_values -> variable,指定数组中 missing value;
  • filling_values -> variable,指定 filling_values,来替代 missing_value;
  • usercols -> sequence,指定需读取的列数, 0 表示第一列,-1 为最后一列;

上面列举出各参数基本用法后,下面将针对里面每个参数,结合实例详细介绍其用法

fname 参数

入的 fname 是以 gz 结尾的话,读取时会在加载数据之前自动解压,但较为常见的都是 txt 文本

delimiter参数

当 delimiter 为字符时,表示分割符,元素以分割符进行分割

>>> data = u"1, 2, 3\n4, 5, 6"
>>> np.genfromtxt(StringIO(data), delimiter=",")
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])
1
2
3
4

当 delimiter 表示整数元组时,代表每一列所在元素最大宽度;如下定义了每一列元素最大宽度分别为4,3,2;

>>> data = u"  1  2  3\n  4  5 67\n890123  4"
>>> np.genfromtxt(StringIO(data), delimiter=3)
array([[   1.,    2.,    3.],
       [   4.,    5.,   67.],
       [ 890.,  123.,    4.]])
>>> data = u"123456789\n   4  7 9\n   4567 9"
>>> np.genfromtxt(StringIO(data), delimiter=(4, 3, 2))
array([[ 1234.,   567.,    89.],
       [    4.,     7.,     9.],
       [    4.,   567.,     9.]])
1
2
3
4
5
6
7
8
9
10

autostrip 参数

对于每行字符串用 分割符分割后,得到的单个元素可能会含有一些制表符或空格等标识符;autostrip 参数设为 True,元素中的空格标识符会被自动删除~

>>> data = u"1, abc , 2\n 3, xxx, 4"
>>> # Without autostrip
>>> np.genfromtxt(StringIO(data), delimiter=",", dtype="|U5")
array([['1', ' abc ', ' 2'],
       ['3', ' xxx', ' 4']], dtype='<U5')
>>> # With autostrip
>>> np.genfromtxt(StringIO(data), delimiter=",", dtype="|U5", autostrip=True)
array([['1', 'abc', '2'],
       ['3', 'xxx', '4']], dtype='<U5')
1
2
3
4
5
6
7
8
9

comments 参数

comments表示注释标识符,指定后注释标识符所在行后面的字符会被自动省略,如下:

>>> data = u"""#
... # Skip me !
... # Skip me too !
... 1, 2
... 3, 4
... 5, 6 #This is the third line of the data
... 7, 8
... # And here comes the last line
... 9, 0
... """
>>> np.genfromtxt(StringIO(data), comments="#", delimiter=",")
array([[1., 2.],
       [3., 4.],
       [5., 6.],
       [7., 8.],
       [9., 0.]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

skip_header,skip_footer

读取数据时,可能前几行后者后几行的数据我们不需要,此时设定 skip_header、skip_footer 参数即可,例如读取时 想过滤数据列表中 前三行、后五行数据,此时参数设定时 skip_header=3,skip_footer=5 即可

>>> data = u"\n".join(str(i) for i in range(10))
>>> np.genfromtxt(StringIO(data),)
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
>>> np.genfromtxt(StringIO(data),
...               skip_header=3, skip_footer=5)
array([ 3.,  4.])
1
2
3
4
5
6

usecols

usecols 参数来指定只读取数据中指定的列,与数组索引用法相似,下面是只提取原数据中第一列和最后一列数据:

>>> data = u"1 2 3\n4 5 6"
>>> np.genfromtxt(StringIO(data), usecols=(0, -1))
array([[ 1.,  3.],
       [ 4.,  6.]])
1
2
3
4

converters

converters 用来对数组中一些数据进行格式替换,以字典形式定义 key 表示需要数据转化的列索引,value 为转换函数,下面实例中将百分比转化为浮点型

>>> data = u"1, , 3\n 4, 5, 6"
>>> convert = lambda x: float(x.strip() or -999)
>>> np.genfromtxt(StringIO(data), delimiter=",",
...               converters={1: convert})
array([[   1., -999.,    3.],
       [   4.,    5.,    6.]])
1
2
3
4
5
6

missing_values,filling_values

读取的数据中一般出现缺失值,而这些缺失值有时对最终分析结果影响很大,我们需要做的就是将这些缺失值用某些值来代替,这里就需要用到 missing_values 、filling_values ,前者标记缺失值,后者对missing_values 进行填充 ,

例如下面的实例,分别将 0,1,2 列数据中的 'N/A'、空格、‘???’ 替换为 0,0,-999;

>>> data = u"N/A, 2, 3\n4, ,???"
>>> kwargs = dict(delimiter=",",
...               dtype=int,
...               names="a,b,c",
...               missing_values={0:"N/A", 'b':" ", 2:"???"},
...               filling_values={0:0, 'b':0, 2:-999})
>>> np.genfromtxt(StringIO(data), **kwargs)
array([(0, 2, 3), (4, 0, -999)],
      dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<i8')])
1
2
3
4
5
6
7
8
9
上次更新: 2025/06/25, 11:25:50
伪随机数生成
机器学习术语

← 伪随机数生成 机器学习术语→

最近更新
01
帮助信息查看
06-08
02
常用命令
06-08
03
学习资源
06-07
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Geeks_Z | MIT License
京公网安备 11010802040735号 | 京ICP备2022029989号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式