python numpy 矩阵堆叠实例

1. 简介

Python作为一门高级编程语言,不仅可以进行一般的编程任务,还拥有很多扩展库,如 NumPy库,它是Python科学计算的基础包,提供了高效的多维数组对象以及用于数组计算的函数。NumPy是Python数据分析最重要的库之一,它不仅能够处理各种数据类型,而且能够进行各种数学运算。

2. NumPy库简介

NumPy是Numerical Python的缩写,是一个开源的Python库。它的主要运用领域是:线性代数、傅立叶变换、随机数生成等。最重要的是,NumPy是Python进行科学计算必不可少的库。

下面来简单介绍一下NumPy中最重要的一个对象——数组对象ndarray。它主要有以下特点:

2.1 数组对象ndarray

元素类型相同:同一个数组对象中只能存放相同类型的元素,这一点也为它带来了非常高效的存储和计算。

维数:ndarray是多维数组,可具有一维到多维不等的不同维度。

数组对象的形状:ndarray可以使用shape属性来确定数组对象的形状。

广播功能:NumPy可以将不同形状的数组对象进行计算,而不用重复元素,这一点也极大的简化了代码。

NumPy库提供了丰富的API,可以完成数组对象的创建、函数计算、数据排序、IO等一系列操作。这里介绍其中的一个函数——stack()。

3. numpy.stack() 函数

numpy.stack()函数用于将sequence类型的相同形状的数组对象,并排堆叠起来,产生新的数组对象。

stack()函数语法如下所示:

numpy.stack(arrays, axis=0)

arrays :需要堆叠的相同形状的数组序列。

axis :堆叠的方式,该值为0时,则是向下增加一个维度。

4. numpy.stack() 简单示例

import numpy as np

a = np.array([[1, 2],

[3, 4]])

b = np.array([[5, 6],

[7, 8]])

c = np.stack((a, b), axis=0) # 数组堆叠

print(c)

以上代码将两个相同形状的数组对象进行了堆叠。其中,参数axis为0时,表示在行的方向上增加一维,输出结果如下:

[[[1 2]

[3 4]]

[[5 6]

[7 8]]]

我们发现增加了一维,而其他部分没有变化。

5. 案例分析:使用stack实现矢量化语言模型

这里我们使用根据前文所述的stack()函数,实现矢量化的语言模型。

5.1 矢量化语言模型原理

这里我们介绍一种常用的语言模型——N-gram模型。该模型中的N的取值范围一般是1到5,通过遍历训练集然后记录下来统计每一种相邻的两个或几个元素,这样可以获得一个词典和统计结果的数组。

因为我们需要对一段新的文本进行语言模型的计算,也就是对模型进行测试,我们需要将新的文本切分成相邻的N个词组,在这个过程中,根据训练集获得的元素也需要进行相同的切分操作,然后计算出各个元素的累计概率,最终得出语言模型的概率结果。

我们假设:P(word|context) 表示在给定context条件下生成word的概率; while N=2时,context和word之间是相邻的两个词。

比如:对于下面的文本序列:

['today', 'is', 'a', 'good', 'day']

可以把它切分为:

['', 'today'], ['today', 'is'], ['is', 'a'], ['a', 'good'], ['good', 'day'], ['day', '']

其中是边界标记,用于标识句子开始和结束。

我们将它们表现为两个数组,一个记录上文context,一个记录下文word,数组元素的顺序与文本的顺序一一对应。

5.2 编写代码实现

首先,定义一个 N-gram 模型的类:

class NgramModel:

def __init__(self, n=2):

self.n = n

def build(self, sent_list):

self.word_list = []

self.context_list = []

self.vocab = set()

for sent in sent_list:

# 创建context和word的切片列表并增加到数组中

words = ['']*(self.n-1) + sent + ['']

for i in range(self.n-1, len(words)):

context = words[i-self.n+1:i]

word = words[i]

self.word_list.append(word)

self.context_list.append(context)

#增加词库

self.vocab.add(word)

self.vocab = sorted(self.vocab)

self.vocab_size = len(self.vocab)

#生成context和word对应的ID

self.word2id = {w:i for (i, w) in enumerate(self.vocab)}

self.id2word = {i:w for (i, w) in enumerate(self.vocab)}

def get_matrix(self, temperature=0.6):

# 矩阵初始化

mat = np.zeros((self.vocab_size, self.vocab_size))

# 对语言模型中的两个统计数组进行for循环

for word, context in zip(self.word_list, self.context_list):

# 获得word和context对应的ID

word_id = self.word2id[word]

context_id = [self.word2id[x] for x in context]

# 填充矩阵

mat[context_id, word_id] += 1

# 使用softmax函数调整概率值

mat = mat / temperature

mat = np.exp(mat)

mat = mat / np.sum(mat, axis=1, keepdims=True)

return mat

在这个代码段中,我们定义了一个 NgramModel 的类并且实现了两个主要的函数—— build() 和 get_matrix()。

其中, NgramModel类是一个类模板,在其初始化 Function 中,我们将 Ngram 模型的维数赋值给成员变量self.n,然后使用 build()函数构建语言模型。在返回词汇表书时,我们可以使用 self.word2id 来查找单词的索引或使用反向字典self.id2word查找单词:

ngram_model = NgramModel(n=2)

sent_list = [['today', 'is', 'a', 'good', 'day']]

ngram_model.build(sent_list)

print("词库大小: ", ngram_model.vocab_size)

print("单词列表: ", ngram_model.vocab)

word_ids = [ngram_model.word2id[w] for w in ngram_model.vocab]

print("单词ID列表: ", word_ids)

id_words = [ngram_model.id2word[i] for i in range(ngram_model.vocab_size)]

print("ID单词列表: ", id_words)

上述代码中,我们对建立好的语言模型查询“词库大小”、“单词列表”、“单词ID列表”以及“ID单词列表”,结果如下:

词库大小: 7

单词列表: ['', '', 'a', 'day', 'good', 'is', 'today']

单词ID列表: [0, 1, 2, 3, 4, 5, 6]

ID单词列表: ['', '', 'a', 'day', 'good', 'is', 'today']

接下来,get_matrix()函数实现了矩阵的自动化填充,并使用softmax函数对其进行整合:

mat = ngram_model.get_matrix()

print("矩阵形状: ", mat.shape)

print("as 计算矩阵温度:", 0.6)

print("矩阵: ", mat)

上述代码会调用 get_matrix()函数来获得填充好的矩阵。由于我们使用了numpy的stack函数,使得我们可以将多个数组对象进行堆叠,因此我们可以随时增加多个语料库,并将新的语料库堆叠到原有矩阵的底部,以扩充语言模型:

sent_list = [['today', 'is', 'a', 'good', 'day'],

['happy', 'day'],

['all', 'good', 'things', 'come', 'to', 'an', 'end']]

ngram_model.build(sent_list)

mat = np.vstack([mat, ngram_model.get_matrix()]) #堆叠

print(mat.shape)

当我们增加了两个新的语料库之后,矩阵的维度增加为:

(3, 7, 7)

这代表有 3 个语言模型矩阵,每个矩阵都包含 7 行和 7 列。对于每个矩阵,行代表上文context (2-gram),列代表下文word,矩阵中的每个单元代表将context映射到word的相对概率。

6. 结论

NumPy库是 Python 进行科学计算必不可少的库之一,但是它并不完全适用于机器学习中的所有方法。本文介绍了 stack() 函数的简单用法,然后基于它实现了一个矢量化的语言模型,并在处理多个数据集时进行了多维数组堆叠。这些例子有利于初学者学习NumPy库并加深对其用法的理解。

后端开发标签