人工智能与 Python(第二节)

201 阅读42分钟

1. 人工智能与 Python – 逻辑编程

2. 无监督学习:聚类

3. 自然语言处理

4. 人工智能与 Python——NLTK 包

5. 分析时间序列数据

6. 人工智能与 Python——语音识别

人工智能与 Python – 逻辑编程

在本章中,我们将重点关注逻辑编程及其对人工智能的帮助。

我们已经知道,逻辑是对正确推理原则的研究,或者简单地说,它是对什么之后发生什么的研究。例如,如果两个陈述为真,那么我们可以从中推断出任何第三个陈述。

概念

逻辑编程是逻辑和编程这两个词的组合。逻辑编程是一种编程范式,其中问题通过程序语句表达为事实和规则,但在形式逻辑系统中。就像面向对象、函数式、声明式和过程式等其他编程范式一样,它也是一种特殊的编程方式。

如何解决逻辑编程问题

逻辑编程使用事实和规则来解决问题。这就是为什么它们被称为逻辑编程的构建块。逻辑编程中的每个程序都需要指定一个目标。要了解如何在逻辑编程中解决问题,我们需要了解构建块 - 事实和规则 -

事实

实际上,每个逻辑程序都需要事实来处理,以便它可以实现给定的目标。事实基本上是关于程序和数据的真实陈述。例如,德里是印度的首都。

规则

实际上,规则是使我们能够对问题域做出结论的约束。规则基本上写成逻辑子句来表达各种事实。例如,如果我们正在构建任何游戏,那么必须定义所有规则。

规则对于解决逻辑编程中的任何问题都非常重要。规则基本上是能够表达事实的逻辑结论。以下是规则的语法 -

A∶− B1,B2,...,B n。

在这里,A 是头部,B1、B2、... Bn 是身体。

例如 - 祖先(X,Y): - 父亲(X,Y)。

祖先(X,Z):- 父亲(X,Y),祖先(Y,Z)。

这可以理解为,对于每个 X 和 Y,如果 X 是 Y 的父亲并且 Y 是 Z 的祖先,则 X 是 Z 的祖先。对于每个 X 和 Y,X 是 Z 的祖先,如果 X 是Y 和 Y 的父亲是 Z 的祖先。

安装有用的包

为了在 Python 中开始逻辑编程,我们需要安装以下两个包 -

观连

它为我们提供了一种方法来简化我们为业务逻辑编写代码的方式。它让我们根据规则和事实表达逻辑。以下命令将帮助您安装 kanren -

pip install kanren

同情心

SymPy 是一个用于符号数学的 Python 库。它旨在成为一个功能齐全的计算机代数系统 (CAS),同时保持代码尽可能简单,以便易于理解和扩展。以下命令将帮助您安装 SymPy -

pip install sympy

逻辑编程的例子

以下是一些可以通过逻辑编程解决的例子 -

匹配数学表达式

实际上,我们可以通过非常有效的方式使用逻辑编程来找到未知值。以下 Python 代码将帮助您匹配数学表达式 -

首先考虑导入以下包 -

from kanren import run, var, fact

from kanren.assoccomm import eq_assoccomm as eq

from kanren.assoccomm import commutative, associative

我们需要定义我们将要使用的数学运算 -

add = 'add'

mul = 'mul'

加法和乘法都是交际过程。因此,我们需要指定它,这可以按如下方式完成 -

fact(commutative, mul)

fact(commutative, add)

fact(associative, mul)

fact(associative, add)

必须定义变量;这可以按如下方式完成 -

a, b = var('a'), var('b')

我们需要将表达式与原始模式相匹配。我们有以下原始模式,基本上是 (5+a)*b -

Original_pattern = (mul, (add, 5, a), b)

我们有以下两个表达式来匹配原始模式 -

exp1 = (mul, 2, (add, 3, 1))

exp2 = (add,5,(mul,8,1))

可以使用以下命令打印输出 -

print(run(0, (a,b), eq(original_pattern, exp1)))

print(run(0, (a,b), eq(original_pattern, exp2)))

运行此代码后,我们将获得以下输出 -

((3,2))

()

第一个输出表示 ab的值。第一个表达式与原始模式匹配并返回****ab的值,但第二个表达式与原始模式不匹配,因此没有返回任何内容。

检查质数

借助逻辑编程,我们可以从数字列表中找出素数,也可以生成素数。下面给出的 Python 代码将从数字列表中找到素数,并将生成前 10 个素数。

让我们首先考虑导入以下包 -

from kanren import isvar, run, membero

from kanren.core import success, fail, goaleval, condeseq, eq, var

from sympy.ntheory.generate import prime, isprime

import itertools as it

现在,我们将定义一个名为 prime_check 的函数,它将根据给定的数字作为数据检查素数。

def prime_check(x):

if isvar(x):

   return condeseq([(eq,x,p)] for p in map(prime, it.count(1)))

else:

   return success if isprime(x) else fail

现在,我们需要声明一个将要使用的变量 -

x = var()

print((set(run(0,x,(membero,x,(12,14,15,19,20,21,22,23,29,30,41,44,52,62,65,85)),

(prime_check,x)))))

print((run(10,x,prime_check(x))))

上述代码的输出如下 -

{19, 23, 29, 41}

(2, 3, 5, 7, 11, 13, 17, 19, 23, 29)

解决难题

逻辑编程可用于解决许多问题,如 8 拼图、斑马拼图、数独、N 皇后等。这里我们以斑马拼图的变体为例,如下所示 -

There are five houses.

The English man lives in the red house.

The Swede has a dog.

The Dane drinks tea.

The green house is immediately to the left of the white house.

They drink coffee in the green house.

The man who smokes Pall Mall has birds.

In the yellow house they smoke Dunhill.

In the middle house they drink milk.

The Norwegian lives in the first house.

The man who smokes Blend lives in the house next to the house with cats.

In a house next to the house where they have a horse, they smoke Dunhill.

The man who smokes Blue Master drinks beer.

The German smokes Prince.

The Norwegian lives next to the blue house.

They drink water in a house next to the house where they smoke Blend.

我们正在借助 Python解决谁拥有 zebra 问题。

让我们导入必要的包 -

from kanren import *

from kanren.core import lall

import time

现在,我们需要定义两个函数 - left()next() 来检查谁的房子在左边或在谁的房子旁边 -

def left(q, p, list):

   return membero((q,p), zip(list, list[1:]))

def next(q, p, list):

   return conde([left(q, p, list)], [left(p, q, list)])

现在,我们将声明一个变量 house 如下 -

houses = var()

我们需要在 lall 包的帮助下定义规则,如下所示。

有 5 间房子 −

rules_zebraproblem = lall(

   (eq, (var(), var(), var(), var(), var()), houses),

 

   (membero,('Englishman', var(), var(), var(), 'red'), houses),

   (membero,('Swede', var(), var(), 'dog', var()), houses),

   (membero,('Dane', var(), 'tea', var(), var()), houses),

   (left,(var(), var(), var(), var(), 'green'),

   (var(), var(), var(), var(), 'white'), houses),

   (membero,(var(), var(), 'coffee', var(), 'green'), houses),

   (membero,(var(), 'Pall Mall', var(), 'birds', var()), houses),

   (membero,(var(), 'Dunhill', var(), var(), 'yellow'), houses),

   (eq,(var(), var(), (var(), var(), 'milk', var(), var()), var(), var()), houses),

   (eq,(('Norwegian', var(), var(), var(), var()), var(), var(), var(), var()), houses),

   (next,(var(), 'Blend', var(), var(), var()),

   (var(), var(), var(), 'cats', var()), houses),

   (next,(var(), 'Dunhill', var(), var(), var()),

   (var(), var(), var(), 'horse', var()), houses),

   (membero,(var(), 'Blue Master', 'beer', var(), var()), houses),

   (membero,('German', 'Prince', var(), var(), var()), houses),

   (next,('Norwegian', var(), var(), var(), var()),

   (var(), var(), var(), var(), 'blue'), houses),

   (next,(var(), 'Blend', var(), var(), var()),

   (var(), var(), 'water', var(), var()), houses),

   (membero,(var(), var(), var(), 'zebra', var()), houses)

)

现在,使用前面的约束运行求解器 -

solutions = run(0, houses, rules_zebraproblem)

借助以下代码,我们可以从求解器中提取输出 -

output_zebra = [house for house in solutions[0] if 'zebra' in house][0][0]

以下代码将有助于打印解决方案 -

print ('\n'+ output_zebra + 'owns zebra.')

上述代码的输出如下 -

German owns zebra.

人工智能与 Python - 无监督学习:聚类

无监督机器学习算法没有任何监督者提供任何类型的指导。这就是为什么它们与某些人所说的真正的人工智能密切相关。

在无监督学习中,没有正确答案,也没有老师指导。算法需要发现数据中有趣的模式以进行学习。

什么是聚类?

基本上,它是一种无监督学习方法,是许多领域使用的统计数据分析的常用技术。聚类主要是将一组观察值划分为子集(称为聚类)的任务,使得同一聚类中的观察值在某种意义上相似,而与其他聚类中的观察值不同。简而言之,我们可以说聚类的主要目标是根据相似性和不相似性对数据进行分组。

例如,下图显示了不同集群中的类似数据 -

聚类

聚类数据的算法

以下是一些用于聚类数据的常用算法 -

K均值算法

K-均值聚类算法是众所周知的数据聚类算法之一。我们需要假设集群的数量是已知的。这也称为平面聚类。它是一种迭代聚类算法。该算法需要遵循以下步骤 -

1 - 我们需要指定所需数量的 K 个子组。

2 - 固定簇数并将每个数据点随机分配给一个簇。或者换句话说,我们需要根据聚类的数量对数据进行分类。

在此步骤中,应计算聚类质心。

由于这是一个迭代算法,我们需要在每次迭代中更新 K 个质心的位置,直到我们找到全局最优值,或者换句话说,质心到达它们的最佳位置。

以下代码将有助于在 Python 中实现 K 均值聚类算法。我们将使用 Scikit-learn 模块。

让我们导入必要的包 -

import matplotlib.pyplot as plt

import seaborn as sns; sns.set()

import numpy as np

from sklearn.cluster import KMeans

下面的代码行将通过使用 sklearn.dataset包中的make_blob来帮助生成包含四个 blob 的二维数据集。

from sklearn.datasets.samples_generator import make_blobs

 

X, y_true = make_blobs(n_samples = 500, centers = 4,

            cluster_std = 0.40, random_state = 0)

我们可以使用以下代码可视化数据集 -

plt.scatter(X[:, 0], X[:, 1], s = 50);

plt.show()

K均值算法

在这里,我们将 kmeans 初始化为 KMeans 算法,所需的参数是多少个簇 (n_clusters)。

kmeans = KMeans(n_clusters = 4)

我们需要用输入数据训练 K-means 模型。

kmeans.fit(X)

y_kmeans = kmeans.predict(X)

plt.scatter(X[:, 0], X[:, 1], c = y_kmeans, s = 50, cmap = 'viridis')

 

centers = kmeans.cluster_centers_

下面给出的代码将帮助我们根据我们的数据绘制和可视化机器的发现,并根据要找到的集群数量进行拟合。

plt.scatter(centers[:, 0], centers[:, 1], c = 'black', s = 200, alpha = 0.5);

plt.show()

K均值算法2

均值漂移算法

它是无监督学习中使用的另一种流行且功能强大的聚类算法。它不做任何假设,因此它是一种非参数算法。它也称为层次聚类或均值漂移聚类分析。以下是该算法的基本步骤 -

·         首先,我们需要从将数据点分配到一个属于自己的集群开始。

·         现在,它计算质心并更新新质心的位置。

·         通过重复这个过程,我们靠近集群的峰值,即向更高密度的区域移动。

·         该算法在质心不再移动的阶段停止。

在以下代码的帮助下,我们正在 Python 中实现 Mean Shift 聚类算法。我们将使用 Scikit-learn 模块。

让我们导入必要的包 -

import numpy as np

from sklearn.cluster import MeanShift

import matplotlib.pyplot as plt

from matplotlib import style

style.use("ggplot")

以下代码将通过使用 sklearn.dataset包中的make_blob来帮助生成包含四个 blob 的二维数据集。

from sklearn.datasets.samples_generator import make_blobs

我们可以使用以下代码可视化数据集

centers = [[2,2],[4,5],[3,10]]

X, _ = make_blobs(n_samples = 500, centers = centers, cluster_std = 1)

plt.scatter(X[:,0],X[:,1])

plt.show()

均值偏移算法

现在,我们需要使用输入数据训练 Mean Shift 聚类模型。

ms = MeanShift()

ms.fit(X)

labels = ms.labels_

cluster_centers = ms.cluster_centers_

以下代码将根据输入数据打印聚类中心和预期的聚类数量 -

print(cluster_centers)

n_clusters_ = len(np.unique(labels))

print("Estimated clusters:", n_clusters_)

[[ 3.23005036 3.84771893]

[ 3.02057451 9.88928991]]

Estimated clusters: 2

下面给出的代码将有助于根据我们的数据绘制和可视化机器的发现,并根据要找到的集群数量进行拟合。

colors = 10*['r.','g.','b.','c.','k.','y.','m.']

   for i in range(len(X)):

   plt.plot(X[i][0], X[i][1], colors[labels[i]], markersize = 10)

plt.scatter(cluster_centers[:,0],cluster_centers[:,1],

   marker = "x",color = 'k', s = 150, linewidths = 5, zorder = 10)

plt.show()

簇数

测量集群性能

真实世界的数据不会自然地组织成许多独特的集群。由于这个原因,不容易想象和举一反三。这就是为什么我们需要测量聚类性能及其质量。它可以在轮廓分析的帮助下完成。

剪影分析

该方法可用于通过测量聚类之间的距离来检查聚类的质量。基本上,它提供了一种通过给出轮廓分数来评估参数(如聚类数量)的方法。该分数是衡量一个集群中的每个点与相邻集群中的点的接近程度的指标。

轮廓评分分析

分数的范围为 [-1, 1]。以下是对该分数的分析 -

·         +1 的分数− 接近 +1 的分数表示样本远离相邻簇。

·         分数为 0 - 分数 0 表示样本位于或非常接近两个相邻集群之间的决策边界。

·         -1 - 负分表示样本已分配到错误的簇。

计算轮廓分数

在本节中,我们将学习如何计算轮廓分数。

轮廓分数可以使用以下公式计算 -

剪影分数=(pq)max(p,q)剪影分数 = \frac{\left ( pq \right )}{max\left ( p,q \right )}

这里,𝑝 是到最近集群中数据点不属于的点的平均距离。并且,𝑞 是到其自身集群中所有点的平均集群内距离。

为了找到最佳的聚类数量,我们需要通过从sklearn 包中导入 metrics模块再次运行聚类算法。在下面的例子中,我们将运行 K-means 聚类算法来找到最佳的聚类数 -

如图所示导入必要的包 -

import matplotlib.pyplot as plt

import seaborn as sns; sns.set()

import numpy as np

from sklearn.cluster import KMeans

在以下代码的帮助下,我们将使用 sklearn.dataset包中的make_blob生成包含四个 blob 的二维数据集。

from sklearn.datasets.samples_generator import make_blobs

 

X, y_true = make_blobs(n_samples = 500, centers = 4, cluster_std = 0.40, random_state = 0)

如图所示初始化变量 -

scores = []

values = np.arange(2, 10)

我们需要通过所有值迭代 K-means 模型,还需要使用输入数据对其进行训练。

for num_clusters in values:

kmeans = KMeans(init = 'k-means++', n_clusters = num_clusters, n_init = 10)

kmeans.fit(X)

现在,使用欧几里得距离度量估计当前聚类模型的轮廓分数 -

score = metrics.silhouette_score(X, kmeans.labels_,

metric = 'euclidean', sample_size = len(X))

以下代码行将有助于显示聚类数量和 Silhouette 分数。

print("\nNumber of clusters =", num_clusters)

print("Silhouette score =", score)

scores.append(score)

您将收到以下输出 -

Number of clusters = 9

Silhouette score = 0.340391138371

 

num_clusters = np.argmax(scores) + values[0]

print('\nOptimal number of clusters =', num_clusters)

现在,最佳簇数的输出如下 -

Optimal number of clusters = 2

寻找最近的邻居

如果我们想要构建推荐系统,例如电影推荐系统,那么我们需要了解寻找最近邻居的概念。这是因为推荐系统利用了最近邻居的概念。

寻找最近邻的概念可以定义为从给定数据集中寻找离输入点最近的点的过程。这个KNN)K-nearest neighbors)算法的主要用途是构建分类系统,根据输入数据点的接近度将数据点分类为各种类别。

下面给出的 Python 代码有助于找到给定数据集的 K 最近邻 -

如下所示导入必要的包。在这里,我们使用sklearn包中的NearestNeighbors 模块

import numpy as np

import matplotlib.pyplot as plt

from sklearn.neighbors import NearestNeighbors

现在让我们定义输入数据 -

A = np.array([[3.1, 2.3], [2.3, 4.2], [3.9, 3.5], [3.7, 6.4], [4.8, 1.9],

             [8.3, 3.1], [5.2, 7.5], [4.8, 4.7], [3.5, 5.1], [4.4, 2.9],])

现在,我们需要定义最近的邻居 -

k = 3

我们还需要提供从中找到最近邻居的测试数据 -

test_data = [3.3, 2.9]

以下代码可以可视化和绘制我们定义的输入数据 -

plt.figure()

plt.title('Input data')

plt.scatter(A[:,0], A[:,1], marker = 'o', s = 100, color = 'black')

寻找最近的邻居

现在,我们需要构建 K 最近邻。对象也需要训练

knn_model = NearestNeighbors(n_neighbors = k, algorithm = 'auto').fit(X)

distances, indices = knn_model.kneighbors([test_data])

现在,我们可以如下打印 K 个最近的邻居

print("\nK Nearest Neighbors:")

for rank, index in enumerate(indices[0][:k], start = 1):

   print(str(rank) + " is", A[index])

我们可以将最近的邻居与测试数据点一起可视化

plt.figure()

plt.title('Nearest neighbors')

plt.scatter(A[:, 0], X[:, 1], marker = 'o', s = 100, color = 'k')

plt.scatter(A[indices][0][:][:, 0], A[indices][0][:][:, 1],

   marker = 'o', s = 250, color = 'k', facecolors = 'none')

plt.scatter(test_data[0], test_data[1],

   marker = 'x', s = 100, color = 'k')

plt.show()

测试数据点

输出

K 最近邻

1 is [ 3.1 2.3]

2 is [ 3.9 3.5]

3 is [ 4.4 2.9]

K-最近邻分类器

K 最近邻 (KNN) 分类器是一种使用最近邻算法对给定数据点进行分类的分类模型。我们已经在上一节中实现了 KNN 算法,现在我们将使用该算法构建一个 KNN 分类器。

KNN分类器的概念

K 最近邻分类的基本概念是找到一个预定义的数目,即距离最近的训练样本的'k' - 必须分类的新样本。新样本将从邻居本身获得标签。KNN 分类器有一个固定的用户定义常数,用于确定必须确定的邻居数。对于距离,标准欧氏距离是最常见的选择。KNN 分类器直接在学习样本上工作,而不是创建学习规则。KNN 算法是所有机器学习算法中最简单的一种。它在大量的分类和回归问题中取得了相当成功,例如字符识别或图像分析。

例子

我们正在构建一个 KNN 分类器来识别数字。为此,我们将使用 MNIST 数据集。我们将在 Jupyter Notebook 中编写此代码。

如下所示导入必要的包。

这里我们使用sklearn.neighbors包中的KNeighborsClassifier模块-

from sklearn.datasets import *

import pandas as pd

%matplotlib inline

from sklearn.neighbors import KNeighborsClassifier

import matplotlib.pyplot as plt

import numpy as np

以下代码将显示数字图像以验证我们必须测试的图像 -

def Image_display(i):

   plt.imshow(digit['images'][i],cmap = 'Greys_r')

   plt.show()

现在,我们需要加载 MNIST 数据集。实际上共有 1797 张图像,但我们使用前 1600 张图像作为训练样本,其余 197 张图像将保留用于测试目的。

digit = load_digits()

digit_d = pd.DataFrame(digit['data'][0:1600])

现在,在显示图像时我们可以看到如下输出 -

Image_display(0)

图片_显示(0)

0 的图像显示如下 -

图片_显示(0)

图片_显示(9)

9 的图像显示如下 -

图片_显示(9)

数字键()

现在,我们需要创建训练和测试数据集,并将测试数据集提供给 KNN 分类器。

train_x = digit['data'][:1600]

train_y = digit['target'][:1600]

KNN = KNeighborsClassifier(20)

KNN.fit(train_x,train_y)

以下输出将创建 K 最近邻分类器构造函数 -

KNeighborsClassifier(algorithm = 'auto', leaf_size = 30, metric = 'minkowski',

   metric_params = None, n_jobs = 1, n_neighbors = 20, p = 2,

   weights = 'uniform')

我们需要通过提供大于 1600 的任意数字来创建测试样本,这些数字是训练样本。

test = np.array(digit['data'][1725])

test1 = test.reshape(1,-1)

Image_display(1725)

图片_显示(6)

6 的图像显示如下 -

图片_显示(6)

现在我们将预测测试数据如下 -

KNN.predict(test1)

上面的代码将生成以下输出 -

array([6])

现在,考虑以下 -

digit['target_names']

上面的代码将生成以下输出 -

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

人工智能与 Python – 自然语言处理

自然语言处理(NLP)是指使用英语等自然语言与智能系统进行通信的人工智能方法。

当您希望像机器人这样的智能系统按照您的指令执行时,当您希望听到基于对话的临床专家系统的决定等时,需要自然语言处理。

NLP 领域涉及让计算机使用人类使用的自然语言执行有用的任务。NLP 系统的输入和输出可以是 -

·         演讲

·         书面文字

NLP 的组成部分

在本节中,我们将了解 NLP 的不同组件。NLP 有两个组成部分。这些组件描述如下 -

自然语言理解 (NLU)

它涉及以下任务 -

·         将给定的自然语言输入映射为有用的表示。

·         分析语言的不同方面。

自然语言生成 (NLG)

它是从某种内部表征中以自然语言的形式产生有意义的短语和句子的过程。它涉及 -

·         文本规划- 这包括从知识库中检索相关内容。

·         句子规划- 这包括选择所需的单词,形成有意义的短语,设置句子的基调。

·         Text Realization - 这是将句子计划映射到句子结构中。

NLU的难点

NLU 的形式和结构非常丰富;然而,这是模棱两可的。可能会有不同程度的歧义 -

词汇歧义

它处于非常原始的级别,例如单词级别。例如,将“board”这个词当作名词还是动词?

语法级歧义

一个句子可以用不同的方式来解析。例如,“他用红色帽子举起甲虫。” − 他是用帽子举起了甲虫还是他举起了一只戴着红色帽子的甲虫?

指称歧义

使用代词指代某物。例如,Rima 去了 Gauri。她说:“我累了。” − 究竟谁累了?

自然语言处理术语

现在让我们看看 NLP 术语中的一些重要术语。

·         Phonology - 它是系统地组织声音的研究。

·         形态学- 它是对从原始有意义的单位构建单词的研究。

·         Morpheme - 它是一种语言中的原始意义单位。

·         Syntax - 它指的是排列单词来造句。它还涉及确定单词在句子和短语中的结构作用。

·         语义学- 它关注单词的含义以及如何将单词组合成有意义的短语和句子。

·         语用学- 它涉及在不同情况下使用和理解句子以及如何影响句子的解释。

·         Discourse - 它处理前一个句子如何影响下一个句子的解释。

·         World Knowledge - 它包括关于世界的一般知识。

NLP 中的步骤

本节展示 NLP 中的不同步骤。

词法分析

它涉及识别和分析单词的结构。语言词典是指一种语言中的单词和短语的集合。词法分析是将整个文本块分成段落、句子和单词。

句法分析(Parsing)

它涉及分析句子中的单词以了解语法并以显示单词之间关系的方式排列单词。诸如“The school goes to boy”之类的句子被英语句法分析器拒绝了。

语义分析

它从文本中提取确切的含义或字典中的含义。检查文本的意义。它是通过映射任务域中的句法结构和对象来完成的。语义分析器忽略诸如“热冰淇淋”之类的句子。

语篇整合

任何句子的意思都取决于它之前的句子的意思。此外,它还带来紧接句的意思。

语用分析

在此期间,所说的话会根据其实际含义进行重新解释。它涉及推导需要现实世界知识的语言的那些方面。

人工智能与 Python——NLTK 包

在本章中,我们将学习如何开始使用 Natural Language Toolkit 包。

先决条件

如果我们想构建具有自然语言处理的应用程序,那么上下文的变化会使它变得最困难。上下文因素会影响机器理解特定句子的方式。因此,我们需要通过使用机器学习方法来开发自然语言应用程序,以便机器也可以理解人类可以理解上下文的方式。

要构建此类应用程序,我们将使用名为 NLTK(自然语言工具包)的 Python 包。

导入 NLTK

在使用之前我们需要安装 NLTK。它可以在以下命令的帮助下安装 -

pip install nltk

要为 NLTK 构建 conda 包,请使用以下命令 -

conda install -c anaconda nltk

现在安装完 NLTK 包后,我们需要通过 python 命令提示符导入它。我们可以通过在 Python 命令提示符下编写以下命令来导入它 -

import nltk

下载 NLTK 的数据

现在导入 NLTK 后,我们需要下载所需的数据。它可以在 Python 命令提示符下借助以下命令完成 -

nltk.download()

安装其他必要的包

要使用 NLTK 构建自然语言处理应用程序,我们需要安装必要的包。包裹如下 -

基因模拟

它是一个健壮的语义建模库,可用于许多应用程序。我们可以通过执行以下命令来安装它 -

pip install gensim

图案

它用于使gensim包正常工作。我们可以通过执行以下命令来安装它

pip install pattern

标记化、词干提取和词形还原的概念

在本节中,我们将了解什么是标记化、词干化和词形还原。

代币化

它可以定义为将给定文本(即字符序列)分解为称为标记的更小单元的过程。标记可以是单词、数字或标点符号。也叫分词。以下是标记化的一个简单示例 -

输入- 芒果、香蕉、菠萝和苹果都是水果。

输出-代币化

打破给定文本的过程可以在定位单词边界的帮助下完成。单词的结尾和新单词的开头称为单词边界。单词的书写系统和印刷结构会影响边界。

在 Python NLTK 模块中,我们有与标记化相关的不同包,我们可以使用它们根据我们的要求将文本划分为标记。一些包裹如下 -

sent_tokenize 包

顾名思义,这个包会将输入的文本分成句子。我们可以在以下 Python 代码的帮助下导入这个包 -

from nltk.tokenize import sent_tokenize

word_tokenize 包

这个包将输入文本分成单词。我们可以在以下 Python 代码的帮助下导入这个包 -

from nltk.tokenize import word_tokenize

WordPunctTokenizer 包

这个包将输入文本分成单词和标点符号。我们可以在以下 Python 代码的帮助下导入这个包 -

from nltk.tokenize import WordPuncttokenizer

词干提取

在处理单词时,由于语法原因,我们会遇到很多变体。这里的变体概念意味着我们必须处理同一个词的不同形式,如民主、民主民主化。机器非常有必要理解这些不同的词具有相同的基本形式。这样,在我们分析文本时提取单词的基本形式会很有用。

我们可以通过词干来实现这一点。这样,我们可以说词干提取是通过切掉词尾来提取词的基本形式的启发式过程。

在 Python NLTK 模块中,我们有与词干提取相关的不同包。这些包可用于获取单词的基本形式。这些包使用算法。一些包裹如下 -

PorterStemmer 包

这个 Python 包使用 Porter 的算法来提取基本形式。我们可以在以下 Python 代码的帮助下导入这个包 -

from nltk.stem.porter import PorterStemmer

例如,如果我们将单词 “writing” 作为词干提取器的输入,我们将在提取词干后得到单词 “write”

LancasterStemmer 软件包

这个 Python 包将使用 Lancaster 算法来提取基本形式。我们可以在以下 Python 代码的帮助下导入这个包 -

from nltk.stem.lancaster import LancasterStemmer

例如,如果我们将单词 “writing” 作为词干提取器的输入,我们将在提取词干后得到单词 “write”

SnowballStemmer 包

这个 Python 包将使用雪球的算法来提取基本形式。我们可以在以下 Python 代码的帮助下导入这个包 -

from nltk.stem.snowball import SnowballStemmer

例如,如果我们将单词 “writing” 作为词干提取器的输入,我们将在提取词干后得到单词 “write”

所有这些算法都有不同程度的严格性。如果我们比较这三个词干分析器,那么 Porter 词干分析器是最不严格的,而 Lancaster 是最严格的。Snowball 词干提取器在速度和严格性方面都很好用。

词形还原

我们还可以通过词形还原来提取单词的基本形式。它基本上是通过使用词汇和词形分析来完成这项任务的,通常旨在仅删除屈折词尾。任何单词的这种基本形式称为引理。

词干提取和词形还原之间的主要区别在于词汇的使用和词的形态分析。另一个区别是,词干提取通常会折叠派生相关的单词,而词形还原通常只会折叠引理的不同屈折形式。例如,如果我们提供单词 saw 作为输入单词,那么词干提取可能会返回单词“s”,但词形还原会尝试返回单词 see 或 saw,具体取决于标记的使用是动词还是名词。

在 Python NLTK 模块中,我们有以下与词形还原过程相关的包,我们可以使用它来获取单词的基本形式 -

WordNetLemmatizer 包

这个 Python 包将提取单词的基本形式,具体取决于它是用作名词还是用作动词。我们可以在以下 Python 代码的帮助下导入这个包 -

from nltk.stem import WordNetLemmatizer

分块:将数据分成块

它是自然语言处理中的重要过程之一。分块的主要工作是识别词性和名词短语等短短语。我们已经研究了代币化的过程,即代币的创建。分块基本上是这些标记的标签。换句话说,分块会告诉我们句子的结构。

在下一节中,我们将了解不同类型的分块。

分块的类型

分块有两种类型。类型如下 -

分块

在这个分块的过程中,对象、事物等变得更通用,语言变得更抽象。有更多达成协议的机会。在这个过程中,我们缩小。例如,如果我们将“汽车的用途是什么”这个问题分块?我们可能会得到“运输”的答案。

分块

在这个分块的过程中,对象、事物等变得更加具体,语言变得更加渗透。将在分块时检查更深层次的结构。在这个过程中,我们放大。例如,如果我们将“具体讲述一辆车”这个问题分块?我们将获得有关汽车的较小信息。

例子

在这个例子中,我们将使用 Python 中的 NLTK 模块进行名词短语分块,这是一种分块类别,它将在句子中找到名词短语块 -

python 中按照以下步骤实现名词短语分块 -

1 - 在这一步中,我们需要定义分块的语法。它将包含我们需要遵守的规则。

2 - 在这一步中,我们需要创建一个块解析器。它会解析语法并给出输出。

3 - 在最后一步中,输出以树格式生成。

让我们按如下方式导入必要的 NLTK 包 -

import nltk

现在,我们需要定义句子。其中,DT 表示行列式,VBP 表示动词,JJ 表示形容词,IN 表示介词,NN 表示名词。

sentence=[("a","DT"),("clever","JJ"),("fox","NN"),("was","VBP"),

          ("jumping","VBP"),("over","IN"),("the","DT"),("wall","NN")]

现在,我们需要给出语法。在这里,我们将以正则表达式的形式给出语法。

grammar = "NP:{

?*}"

我们需要定义一个解析语法的解析器。

parser_chunking = nltk.RegexpParser(grammar)

解析器解析句子如下 -

parser_chunking.parse(sentence)

接下来,我们需要获取输出。输出在名为output_chunk的简单变量中生成。

Output_chunk = parser_chunking.parse(sentence)

执行以下代码后,我们可以以树的形式绘制输出。

output.draw()

Nltk

词袋 (BoW) 模型

Bag of Word (BoW) 是自然语言处理中的一种模型,主要用于从文本中提取特征,以便将文本用于机器学习算法中的建模。

现在问题来了,为什么我们需要从文本中提取特征。这是因为机器学习算法无法处理原始数据,它们需要数字数据才能从中提取有意义的信息。将文本数据转换为数字数据称为特征提取或特征编码。

怎么运行的

这是从文本中提取特征的非常简单的方法。假设我们有一个文本文档,我们想将它转换成数字数据,或者说想从中提取特征,那么首先这个模型会从文档中的所有单词中提取一个词汇表。然后通过使用文档术语矩阵,它将构建一个模型。这样,BoW 只将文档表示为一个词袋。文档中有关单词顺序或结构的任何信息都将被丢弃。

文档术语矩阵的概念

BoW 算法通过使用文档术语矩阵来构建模型。顾名思义,文档词条矩阵就是文档中出现的各种字数的矩阵。借助这个矩阵,文本文档可以表示为各种单词的加权组合。通过设置阈值并选择更有意义的词,我们可以构建文档中所有词的直方图,可以用作特征向量。以下是理解文档术语矩阵概念的示例 -

例子

假设我们有以下两个句子 -

·         句子 1 - 我们正在使用词袋模型。

·         Sentence 2 - Bag of Words 模型用于提取特征。

现在,通过考虑这两个句子,我们有以下 13 个不同的词 -

现在,我们需要通过使用每个句子中的字数来为每个句子构建一个直方图 -

·         句子 1 - [1,1,1,1,1,1,1,1,0,0,0,0,0]

·         句子 2 - [0,0,0,1,1,1,1,1,1,1,1,1,1]

这样,我们就得到了提取出来的特征向量。每个特征向量都是 13 维的,因为我们有 13 个不同的词。

统计的概念

统计的概念称为 TermFrequency-Inverse Document Frequency (tf-idf)。文件中的每一个字都很重要。统计数据帮助我们理解每个词的重要性。

词频(tf)

它衡量每个词在文档中出现的频率。它可以通过将每个单词的计数除以给定文档中的单词总数来获得。

反向文件频率(idf)

它是衡量给定文档集中一个词对该文档有多独特的度量。为了计算 idf 并制定一个独特的特征向量,我们需要减少像 the 这样的常见词的权重,并权衡不常见的词。

在 NLTK 中构建词袋模型

在本节中,我们将通过使用 CountVectorizer 从这些句子创建向量来定义一个字符串集合。

让我们导入必要的包 -

from sklearn.feature_extraction.text import CountVectorizer

现在定义句子集。

Sentences = ['We are using the Bag of Word model', 'Bag of Word model is

           used for extracting the features.']

 

vectorizer_count = CountVectorizer()

 

features_text = vectorizer.fit_transform(Sentences).todense()

 

print ( vectorizer . vocabulary_ )

上面的程序生成如下所示的输出。它表明我们在上述两个句子中有 13 个不同的词 -

{'we': 11, 'are': 0, 'using': 10, 'the': 8, 'bag': 1, 'of': 7,

 'word': 12, 'model': 6, 'is': 5, 'used': 9, 'for': 4, 'extracting': 2, 'features': 3}

这些是可用于机器学习的特征向量(文本到数字形式)。

解决问题

在本节中,我们将解决一些相关问题。

品类预测

在一组文档中,不仅单词很重要,单词的类别也很重要;特定单词属于哪个文本类别。例如,我们要预测给定的句子是否属于电子邮件、新闻、体育、计算机等类别。在下面的示例中,我们将使用 tf-idf 制定特征向量来查找文档的类别。我们将使用来自 sklearn 的 20 个新闻组数据集的数据。

我们需要导入必要的包 -

from sklearn.datasets import fetch_20newsgroups

from sklearn.naive_bayes import MultinomialNB

from sklearn.feature_extraction.text import TfidfTransformer

from sklearn.feature_extraction.text import CountVectorizer

定义类别地图。我们使用五个不同的类别,分别命名为宗教、汽车、体育、电子和太空。

category_map = {'talk.religion.misc':'Religion','rec.autos''Autos',

   'rec.sport.hockey':'Hockey','sci.electronics':'Electronics', 'sci.space': 'Space'}

创建训练集 -

training_data = fetch_20newsgroups(subset = 'train',

   categories = category_map.keys(), shuffle = True, random_state = 5)

建立一个计数向量化器并提取术语计数 -

vectorizer_count = CountVectorizer()

train_tc = vectorizer_count.fit_transform(training_data.data)

print("\nDimensions of training data:", train_tc.shape)

tf-idf 转换器创建如下 -

tfidf = TfidfTransformer()

train_tfidf = tfidf.fit_transform(train_tc)

现在,定义测试数据 -

input_data = [

   'Discovery was a space shuttle',

   'Hindu, Christian, Sikh all are religions',

   'We must have to drive safely',

   'Puck is a disk made of rubber',

   'Television, Microwave, Refrigrated all uses electricity'

]

以上数据将帮助我们训练多项式朴素贝叶斯分类器 -

classifier = MultinomialNB().fit(train_tfidf, training_data.target)

使用计数向量化器转换输入数据 -

input_tc = vectorizer_count.transform(input_data)

现在,我们将使用 tfidf 转换器转换矢量化数据 -

input_tfidf = tfidf.transform(input_tc)

我们将预测输出类别 -

predictions = classifier.predict(input_tfidf)

输出生成如下 -

for sent, category in zip(input_data, predictions):

   print('\nInput Data:', sent, '\n Category:', \

      category_map[training_data.target_names[category]])

类别预测器生成以下输出 -

Dimensions of training data: (2755, 39297)

 

Input Data: Discovery was a space shuttle

Category: Space

 

Input Data: Hindu, Christian, Sikh all are religions

Category: Religion

 

Input Data: We must have to drive safely

Category: Autos

 

Input Data: Puck is a disk made of rubber

Category: Hockey

 

Input Data: Television, Microwave, Refrigrated all uses electricity

Category: Electronics

性别查找器

在此问题陈述中,将训练分类器通过提供姓名来查找性别(男性或女性)。我们需要使用启发式构造特征向量并训练分类器。我们将使用来自 scikit-learn 包的标记数据。以下是构建性别查找器的 Python 代码 -

让我们导入必要的包 -

import random

 

from nltk import NaiveBayesClassifier

from nltk.classify import accuracy as nltk_accuracy

from nltk.corpus import names

现在我们需要从输入单词中提取最后 N 个字母。这些字母将作为特征 -

def extract_features(word, N = 2):

   last_n_letters = word[-N:]

   return {'feature': last_n_letters.lower()}

              

if name=='main':

使用 NLTK 中可用的标记名称(男性和女性)创建训练数据 -

male_list = [(name, 'male') for name in names.words('male.txt')]

female_list = [(name, 'female') for name in names.words('female.txt')]

data = (male_list + female_list)

 

random.seed(5)

random.shuffle(data)

现在,测试数据将创建如下 -

namesInput = ['Rajesh', 'Gaurav', 'Swati', 'Shubha']

使用以下代码定义用于训练和测试的样本数

train_sample = int(0.8 * len(data))

现在,我们需要遍历不同的长度以便比较准确度 -

for i in range(1, 6):

   print('\nNumber of end letters:', i)

   features = [(extract_features(n, i), gender) for (n, gender) in data]

   train_data, test_data = features[:train_sample],

features[train_sample:]

   classifier = NaiveBayesClassifier.train(train_data)

分类器的准确性可以计算如下 -

accuracy_classifier = round(100 * nltk_accuracy(classifier, test_data), 2)

   print('Accuracy = ' + str(accuracy_classifier) + '%')

现在,我们可以预测输出 -

for name in namesInput:

   print(name, '==>', classifier.classify(extract_features(name, i)))

上面的程序将生成以下输出 -

Number of end letters: 1

Accuracy = 74.7%

Rajesh -> female

Gaurav -> male

Swati -> female

Shubha -> female

 

Number of end letters: 2

Accuracy = 78.79%

Rajesh -> male

Gaurav -> male

Swati -> female

Shubha -> female

 

Number of end letters: 3

Accuracy = 77.22%

Rajesh -> male

Gaurav -> female

Swati -> female

Shubha -> female

 

Number of end letters: 4

Accuracy = 69.98%

Rajesh -> female

Gaurav -> female

Swati -> female

Shubha -> female

 

Number of end letters: 5

Accuracy = 64.63%

Rajesh -> female

Gaurav -> female

Swati -> female

Shubha -> female

在上面的输出中,我们可以看到最大结束字母数的准确度为 2,并且随着结束字母数的增加而降低。

主题建模:识别文本数据中的模式

我们知道,通常文档会按主题进行分组。有时我们需要识别文本中与特定主题相对应的模式。这样做的技术称为主题建模。换句话说,我们可以说主题建模是一种揭示给定文档集中的抽象主题或隐藏结构的技术。

我们可以在以下场景中使用主题建模技术 -

文本分类

在主题建模的帮助下,分类可以得到改进,因为它将相似的词组合在一起,而不是将每个词单独用作特征。

推荐系统

借助主题建模,我们可以使用相似性度量来构建推荐系统。

主题建模算法

主题建模可以通过使用算法来实现。算法如下 -

潜在狄利克雷分配 (LDA)

该算法是主题建模最流行的算法。它使用概率图形模型来实现主题建模。我们需要在 Python 中导入 gensim 包才能使用 LDA slgorithm。

潜在语义分析(LDA)或潜在语义索引(LSI)

该算法基于线性代数。基本上它在文档术语矩阵上使用 SVD(奇异值分解)的概念。

非负矩阵分解 (NMF)

它也基于线性代数。

上述所有主题建模算法都将主题数作为参数,文档**-** 词矩阵作为输入,WTM (词主题矩阵)TDM (主题文档矩阵) 作为输出。

人工智能与 Python——分析时间序列数据

预测给定输入序列中的下一个是机器学习中的另一个重要概念。本章为您详细介绍分析时间序列数据。

介绍

时间序列数据是指一系列特定时间间隔内的数据。如果我们想在机器学习中建立序列预测,那么我们必须处理序列数据和时间。系列数据是顺序数据的抽象。数据排序是顺序数据的一个重要特征。

序列分析或时间序列分析的基本概念

序列分析或时间序列分析是根据先前观察到的预测给定输入序列中的下一个。预测可以是接下来可能发生的任何事情:一个符号、一个数字、第二天的天气、下一个演讲词等。序列分析在股票市场分析、天气预报和产品推荐等应用中非常方便。

例子

考虑以下示例以了解序列预测。这里A B C D是给定值,您必须使用序列预测模型来预测值E

序列预测模型

安装有用的包

对于使用 Python 的时间序列数据分析,我们需要安装以下包 -

熊猫

Pandas 是一个开源的 BSD 许可库,它为 Python 提供高性能、易于使用的数据结构和数据分析工具。您可以在以下命令的帮助下安装 Pandas -

pip install pandas

如果您正在使用 Anaconda 并想使用conda包管理器进行安装,那么您可以使用以下命令 -

conda install -c anaconda pandas

嗯学习

它是一个开源的 BSD 许可库,由简单的算法和模型组成,用于在 Python 中学习隐马尔可夫模型 (HMM)。您可以借助以下命令安装它 -

pip install hmmlearn

如果您正在使用 Anaconda 并想使用conda包管理器进行安装,那么您可以使用以下命令 -

conda install -c omnia hmmlearn

结构体

它是一个结构化的学习和预测库。在 PyStruct 中实现的学习算法具有诸如条件随机场 (CRF)、最大间隔马尔可夫随机网络 (M3N) 或结构支持向量机等名称。您可以借助以下命令安装它 -

pip install pystruct

CVXOPT

它用于基于Python编程语言的凸优化。它也是一个免费软件包。您可以在以下命令的帮助下安装它 -

pip install cvxopt

如果您正在使用 Anaconda 并想使用conda包管理器进行安装,那么您可以使用以下命令 -

conda install -c anaconda cvdoxt

Pandas:从时间序列数据中处理、切片和提取统计数据

如果您必须处理时间序列数据,Pandas 是一个非常有用的工具。在 Pandas 的帮助下,您可以执行以下操作 -

·         使用 pd.date_range包创建日期范围

·         使用pd.Series包用日期索引熊猫

·         使用ts.resample包执行重新采样

·         改变频率

例子

以下示例向您展示了使用 Pandas 处理和切片时间序列数据。请注意,这里我们使用的是 Monthly Arctic Oscillation 数据,该数据可以从monthly.ao.index.b50.current.ascii下载,并可以转换为文本格式供我们使用。

处理时间序列数据

要处理时间序列数据,您必须执行以下步骤 -

第一步涉及导入以下包 -

import numpy as np

import matplotlib.pyplot as plt

import pandas as pd

接下来,定义一个函数,它将从输入文件中读取数据,如下面的代码所示 -

def read_data(input_file):

   input_data = np.loadtxt(input_file, delimiter = None)

现在,将此数据转换为时间序列。为此,创建我们时间序列的日期范围。在这个例子中,我们将一个月作为数据的频率。我们的文件包含从 1950 年 1 月开始的数据。

dates = pd.date_range('1950-01', periods = input_data.shape[0], freq = 'M')

在此步骤中,我们借助 Pandas Series 创建时间序列数据,如下所示 -

output = pd.Series(input_data[:, index], index = dates)       

return output

              

if name=='main':

输入输入文件的路径,如下所示 -

input_file = "/Users/admin/AO.txt"

现在,将列转换为时间序列格式,如下所示 -

timeseries = read_data(input_file)

最后,使用显示的命令绘制和可视化数据 -

plt.figure()

timeseries.plot()

plt.show()

您将观察到如下图所示的图 -

测试系列

地块

切片时间序列数据

切片涉及仅检索时间序列数据的一部分。作为示例的一部分,我们仅对 1980 年至 1990 年的数据进行切片。观察以下执行此任务的代码 -

timeseries['1980':'1990'].plot()

   <matplotlib.axes._subplots.AxesSubplot at 0xa0e4b00>

 

plt.show()

当您运行用于切片时间序列数据的代码时,您可以观察到下图,如下图所示 -

切片时间序列数据

从时间序列数据中提取统计数据

在需要得出一些重要结论的情况下,您将不得不从给定数据中提取一些统计数据。均值、方差、相关性、最大值和最小值是此类统计数据中的一部分。如果您想从给定的时间序列数据中提取此类统计信息,您可以使用以下代码 -

意思是

您可以使用mean() 函数来计算平均值,如下所示 -

timeseries.mean()

那么您将观察到的所讨论示例的输出是 -

-0.11143128165238671

最大限度

您可以使用max() 函数来查找最大值,如下所示 -

timeseries.max()

那么您将观察到的所讨论示例的输出是 -

3.4952999999999999

最低限度

您可以使用 min() 函数来查找最小值,如下所示 -

timeseries.min()

那么您将观察到的所讨论示例的输出是 -

-4.2656999999999998

一次搞定一切

如果您想一次计算所有统计数据,您可以使用describe() 函数,如下所示 -

timeseries.describe()

那么您将观察到的所讨论示例的输出是 -

count   817.000000

mean     -0.111431

std       1.003151

min      -4.265700

25%      -0.649430

50%      -0.042744

75%       0.475720

max       3.495300

dtype: float64

重采样

您可以将数据重新采样到不同的时间频率。执行重新采样的两个参数是 -

·         时间段

·         方法

用 mean() 重新采样

您可以使用以下代码通过 mean() 方法对数据重新采样,这是默认方法 -

timeseries_mm = timeseries.resample("A").mean()

timeseries_mm.plot(style = 'g--')

plt.show()

然后,您可以观察下图作为使用 mean() 重采样的输出 -

用均值法重新抽样

用 median() 重新采样

您可以使用以下代码使用 median() 方法对数据重新采样-

timeseries_mm = timeseries.resample("A").median()

timeseries_mm.plot()

plt.show()

然后,您可以观察下图作为使用 median() 重新采样的输出 -

用中值法重新抽样

滚动平均值

您可以使用以下代码来计算滚动(移动)平均值 -

timeseries.rolling(window = 12, center = False).mean().plot(style = '-g')

plt.show()

然后,您可以观察下图作为滚动(移动)均值的输出 -

滚动平均值

通过隐马尔可夫模型 (HMM) 分析序列数据

HMM是一种统计模型,广泛应用于时间序列股市分析、健康体检、语音识别等具有连续性和可扩展性的数据。本节详细介绍使用隐马尔可夫模型 (HMM) 分析序列数据。

隐马尔可夫模型 (HMM)

HMM 是一种随机模型,它建立在马尔可夫链的概念之上,该模型基于以下假设:未来统计数据的概率仅取决于当前过程状态,而不是之前的任何状态。比如抛硬币,我们不能说第五次抛的结果就是正面。这是因为一枚硬币没有任何记忆,下一个结果不依赖于上一个结果。

在数学上,HMM 由以下变量组成 -

国家(S)

它是 HMM 中存在的一组隐藏或潜在状态。记为S。

输出符号 (O)

它是 HMM 中存在的一组可能的输出符号。用 O 表示。

状态转移概率矩阵(A)

它是从一个状态转换到其他每个状态的概率。记为A。

观测发射概率矩阵(B)

它是在特定状态下发射/观察符号的概率。记为 B。

先验概率矩阵 (II)

它是从系统的各种状态开始到特定状态的概率。它由 Π 表示。

因此,HMM 可以定义为𝝀 = (S,O,A,B, 𝝅 )

在哪里,

·         S = {s 1 ,s 2 ,...,s N } 是一组 N 个可能的状态,

·         O = {o 1 ,o 2 ,…,o M } 是一组 M 个可能的观测符号,

·         A是N 𝒙 N状态转移概率矩阵(TPM),

·         B 是N 𝒙 M观测值或发射概率矩阵 (EPM),

·         π是一个N维的初始状态概率分布向量。

示例:股票市场数据分析

在此示例中,我们将逐步分析股票市场数据,以了解 HMM 如何处理顺序或时间序列数据。请注意,我们正在用 Python 实现这个例子。

导入必要的包,如下所示 -

import datetime

import warnings

现在,使用 matpotlib.finance包中的股市数据,如下所示 -

import numpy as np

from matplotlib import cm, pyplot as plt

from matplotlib.dates import YearLocator, MonthLocator

try:

   from matplotlib.finance import quotes_historical_yahoo_och1

except ImportError:

   from matplotlib.finance import (

      quotes_historical_yahoo as quotes_historical_yahoo_och1)

 

from hmmlearn.hmm import GaussianHMM

从开始日期和结束日期加载数据,即在两个特定日期之间加载数据,如下所示 -

start_date = datetime.date(1995, 10, 10)

end_date = datetime.date(2015, 4, 25)

quotes = quotes_historical_yahoo_och1('INTC', start_date, end_date)

在这一步中,我们将每天提取收盘价。为此,请使用以下命令 -

closing_quotes = np.array([quote[2] for quote in quotes])

现在,我们将提取每天交易的股票数量。为此,请使用以下命令 -

volumes = np.array([quote[5] for quote in quotes])[1:]

在这里,使用下面显示的代码获取收盘价的百分比差异 -

diff_percentages = 100.0 * np.diff(closing_quotes) / closing_quotes[:-]

dates = np.array([quote[0] for quote in quotes], dtype = np.int)[1:]

training_data = np.column_stack([diff_percentages, volumes])

在此步骤中,创建并训练高斯 HMM。为此,请使用以下代码 -

hmm = GaussianHMM(n_components = 7, covariance_type = 'diag', n_iter = 1000)

with warnings.catch_warnings():

   warnings.simplefilter('ignore')

   hmm.fit(training_data)

现在,使用 HMM 模型生成数据,使用显示的命令 -

num_samples = 300

samples, _ = hmm.sample(num_samples)

最后,在这一步中,我们以图表的形式绘制和可视化交易股票的差异百分比和交易量作为输出。

使用以下代码绘制和可视化差异百分比 -

plt.figure()

plt.title('Difference percentages')

plt.plot(np.arange(num_samples), samples[:, 0], c = 'black')

使用以下代码绘制和可视化交易的股票数量 -

plt.figure()

plt.title('Volume of shares')

plt.plot(np.arange(num_samples), samples[:, 1], c = 'black')

plt.ylim(ymin = 0)

plt.show()