个性化阅读
专注于IT技术分析

NumPy教程:Python机器学习库

本文概述

NumPy是一个Python软件包, 非常适合科学计算。当我们使用Python进行编程时, 它是用于机器学习的非常常见的基础库。

我将在本文中介绍入门教程。

1.简介

NumPy是用于科学计算的基本软件包。它是一种Python语言实现, 其中包括:

  • 强大的N维数组结构
  • 复杂的功能
  • 可以集成到C / C ++和Fortran代码中的工具
  • 线性代数, 傅立叶变换和随机数特征

除了用于科学计算之外, NumPy还可以用作常规数据的有效多维容器。由于NumPy可以处理任何类型的数据, 因此可以无缝且高效地集成到多种类型的数据库中。

2.获取NumPy

由于它是一个Python软件包, 因此你的机器需要配备你首先需要的Python环境。你可以自己在网络上搜索获取方法。

你也可以在scipy.org的官方网站上查看“安装”软件包, 以获取如何获取NumPy。我不会在本文中详细介绍。

我建议使用pip来安装Python软件包的方法。命令如下:

pip3 install numpy

验证和测试本文代码的环境如下:

  • 硬件:MacBook Pro 2015
  • 操作系统:macOS High Sierra
  • 本地:Python 3.6.2
  • 封装:numpy 1.13.3

此外

  • 为了简单起见, 我将通过Python中的print函数验证结果。
  • 为了方便拼写, 默认情况下, 我将import numpy用作np。

3.基本属性和数组创建

NumPy的基础是齐次的多维数据, 并且数组中的元素可以由下标索引。在NumPy中, 维度称为轴(复数是轴), 维度数称为等级。

例如:

这是一个秩为1的数组, 轴的长度为3:

[1, 2, 3]

下面是一个秩为2的数组, 轴的长度也为3:

[[ 1, 2, 3], [ 4, 5, 6]]

我们可以通过array函数创建一个NumPy数组, 例如:

a = np.array([1, 2, 3])
b = np.array([(1, 2, 3), (4, 5, 6)])

请注意, 此处需要方括号。并且以下书写方式是错误的:

a = np.array(1, 2, 3, 4) # WRONG!!!

NumPy的数组类是ndarray, 它具有别名numpy.array, 但与Python标准库中的array.array不同。后者只是一维数组。 ndarray的功能如下:

  • ndarray.ndim:数组的维数。在Python中称为等级。
  • ndarray.shape:数组的维数。它是一系列数字, 其长度由数组的维数(ndim)确定。例如, 长度为n的一维数组的形状为n。 n行m列的数组的形状为n, m。
  • ndarray.size:数组中所有元素的数量。
  • ndarray.dtype:数组中元素的类型, 例如numpy.int32, numpy.int16或numpy.float64。
  • ndarray.itemsize:数组中每个元素的大小, 以字节为单位。
  • ndarray.data:用于存储数组元素的缓冲区。通常, 我们只需要通过下标访问元素, 而无需访问缓冲区。

让我们看一下代码示例:

# create_array.py

import numpy as np

a = np.array([1, 2, 3])
b = np.array([(1, 2, 3), (4, 5, 6)])

print('a=')
print(a)
print("a's ndim {}".format(a.ndim))
print("a's shape {}".format(a.shape))
print("a's size {}".format(a.size))
print("a's dtype {}".format(a.dtype))
print("a's itemsize {}".format(a.itemsize))

print('')

print('b=')
print(b)
print("b's ndim {}".format(b.ndim))
print("b's shape {}".format(b.shape))
print("b's size {}".format(b.size))
print("b's dtype {}".format(b.dtype))
print("b's itemsize {}".format(b.itemsize))

输出如下:

a=
[1 2 3]
a's ndim 1
a's shape (3, )
a's size 3
a's dtype int64
a's itemsize 8

b=
[[1 2 3]
 [4 5 6]]
b's ndim 2
b's shape (2, 3)
b's size 6
b's dtype int64
b's itemsize 8

我们还可以在创建数组时指定元素的类型, 例如:

c = np.array( [ [1, 2], [3, 4] ], dtype=complex )

有关数组函数的更多参数说明, 请参见:numpy.array

注意:NumPy本身支持多维数组, 还支持各种类型的元素的数据。但是考虑到3D及更高版本的数组结构不容易理解, 并且在进行机器学习编程时, 将主要使用矩阵运算, 因此, 接下来, 我将主要使用一维和二维数组作为示例为了显示。

4.创建一个特定的数组

在实际的项目工程中, 我们经常需要一些特定的数据, 并且NumPy中提供了一些帮助程序功能:

  • 零:用于创建一个元素均为0的数组
  • 一:用于创建一个元素均为1的数组
  • 空:用于创建未初始化的数据。因此内容是不确定的。
  • arange:用于通过指定范围和步长来创建数组
  • 行空间:用于通过指定元素的范围和数量来创建数组
  • random:用于生成随机数
# create_specific_array.py

import numpy as np

a = np.zeros((2, 3))
print('np.zeros((2, 3)= \n{}\n'.format(a))

b = np.ones((2, 3))
print('np.ones((2, 3))= \n{}\n'.format(b))

c = np.empty((2, 3))
print('np.empty((2, 3))= \n{}\n'.format(c))

d = np.arange(1, 2, 0.3)
print('np.arange(1, 2, 0.3)= \n{}\n'.format(d))

e = np.linspace(1, 2, 7)
print('np.linspace(1, 2, 7)= \n{}\n'.format(e))

f = np.random.random((2, 3))
print('np.random.random((2, 3))= \n{}\n'.format(f))

输出如下。

np.zeros((2, 3)= 
[[ 0.  0.  0.]
 [ 0.  0.  0.]]

np.ones((2, 3))= 
[[ 1.  1.  1.]
 [ 1.  1.  1.]]

np.empty((2, 3))= 
[[ 1.  1.  1.]
 [ 1.  1.  1.]]

np.arange(1, 2, 0.3)= 
[ 1.   1.3  1.6  1.9]

np.linspace(1, 2, 7)= 
[ 1.          1.16666667  1.33333333  1.5         1.66666667  1.83333333
  2.        ]

np.random.random((2, 3))= 
[[ 0.5744616   0.58700653  0.59609648]
 [ 0.0417809   0.23810732  0.38372978]]

5.形状和操作

除了生成数组之外, 在保存了一些数据之后, 我们可能还需要基于现有数组生成一些新的数据结构。在这种情况下, 我们可以使用以下功能:

  • reshape:用于根据现有数组和指定形状生成新数组
  • vstack:用于在垂直方向上堆叠多个阵列(阵列的尺寸必须匹配)
  • hstack:用于在水平方向上堆叠多个阵列(阵列的尺寸必须匹配)
  • hsplit:用于水平拆分数组
  • vsplit:用于垂直拆分数组

我们将使用一些示例进行说明。

为了使测试更容易, 让我们创建一些数据:

  • zero_line:包含三个0的行的数组
  • one_column:具有包含三个1的列的数组
  • a:2行3列的矩阵
  • b:[11, 20]间隔中的整数数组
# shape_manipulation.py

zero_line = np.zeros((1, 3))
one_column = np.ones((3, 1))
print("zero_line = \n{}\n".format(zero_line))
print("one_column = \n{}\n".format(one_column))

a = np.array([(1, 2, 3), (4, 5, 6)])
b = np.arange(11, 20)
print("a = \n{}\n".format(a))
print("b = \n{}\n".format(b))

我们可以在输出中获得结构:

zero_line = 
[[ 0.  0.  0.]]

one_column = 
[[ 1.]
 [ 1.]
 [ 1.]]

a = 
[[1 2 3]
 [4 5 6]]

b = 
[11 12 13 14 15 16 17 18 19]

数组b最初是一维数组, 我们通过reshape方法将其调整为3行3列的矩阵:

# shape_manipulation.py

b = b.reshape(3, -1)
print("b.reshape(3, -1) = \n{}\n".format(b))

此处的第二个参数设置为-1, 这意味着它将根据实际情况自动确定。由于数组最初具有9个元素, 因此调整大小后的矩阵为3X3。代码输出如下:

b.reshape(3, -1) = 
[[11 12 13]
 [14 15 16]
 [17 18 19]]

接下来, 我们将通过vstack函数垂直堆叠三个数组:

# shape_manipulation.py

c = np.vstack((a, b, zero_line))
print("c = np.vstack((a, b, zero_line)) = \n{}\n".format(c))

输出如下, 请注意堆叠前后的数据结构:

c = np.vstack((a, b, zero_line)) = 
[[  1.   2.   3.]
 [  4.   5.   6.]
 [ 11.  12.  13.]
 [ 14.  15.  16.]
 [ 17.  18.  19.]
 [  0.   0.   0.]]

同样, 我们也可以使用hstack进行水平堆叠。这次我们需要首先调整数组的结构:

# shape_manipulation.py

a = a.reshape(3, 2)
print("a.reshape(3, 2) = \n{}\n".format(a))

d = np.hstack((a, b, one_column))
print("d = np.hstack((a, b, one_column)) = \n{}\n".format(d))

输出如下, 请注意再次堆叠前后的数据结构:

a.reshape(3, 2) = 
[[1 2]
 [3 4]
 [5 6]]

d = np.hstack((a, b, one_column)) = 
[[  1.   2.  11.  12.  13.   1.]
 [  3.   4.  14.  15.  16.   1.]
 [  5.   6.  17.  18.  19.   1.]]

请注意, 如果两个阵列的结构不兼容, 则堆叠将失败。例如, 它将无法执行以下代码行:

# shape_manipulation.py

# np.vstack((a, b)) # ValueError: dimensions not match

这是因为数组a有两列, 而数组b有三列, 所以它们不能堆叠。

接下来, 让我们看一下拆分。首先, 我们将数组d在水平方向上分成三个数组。然后我们打印出中间一个(下标为1):

# shape_manipulation.py

e = np.hsplit(d, 3) # Split a into 3
print("e = np.hsplit(d, 3) = \n{}\n".format(e))
print("e[1] = \n{}\n".format(e[1]))

输出如下:

e = np.hsplit(d, 3) = 
[array([[ 1., 2.], [ 3., 4.], [ 5., 6.]]), array([[ 11., 12.], [ 14., 15.], [ 17., 18.]]), array([[ 13., 1.], [ 16., 1.], [ 19., 1.]])]

e[1] = 
[[ 11.  12.]
 [ 14.  15.]
 [ 17.  18.]]

另外, 如果我们设置的分割数不能使原始数组平均分割, 则操作将失败:

# np.hsplit(d, 4) # ValueError: array split does not result in an equal division

除了指定要均匀分割数组的数字外, 我们还可以指定要分割的列数。下面是从第一列和第三列拆分数组d的操作:

# shape_manipulation.py

f = np.hsplit(d, (1, 3)) # # Split a after the 1st and the 3rd column
print("f = np.hsplit(d, (1, 3)) = \n{}\n".format(f))

代码的输出如下。数组d分为三个数组, 分别包含1、2和3列:

f = np.hsplit(d, (1, 3)) = 
[array([[ 1.], [ 3.], [ 5.]]), array([[  2., 11.], [  4., 14.], [  6., 17.]]), array([[ 12., 13., 1.], [ 15., 16., 1.], [ 18., 19., 1.]])]

最后, 我们在垂直方向上拆分数组d。同样, 如果指定的数字不能使数组均匀分割, 它将失败:

# shape_manipulation.py

g = np.vsplit(d, 3)
print("np.hsplit(d, 2) = \n{}\n".format(g))

# np.vsplit(d, 2) # ValueError: array split does not result in an equal division

np.vsplit(d, 3)将生成三个一维数组:

np.vsplit(d, 3) = 
[array([[  1., 2., 11., 12., 13., 1.]]), array([[  3., 4., 14., 15., 16., 1.]]), array([[  5., 6., 17., 18., 19., 1.]])]

6.索引

接下来, 我们看一下如何访问NumPy数组中的数据。

再次, 为了方便测试, 让我们首先创建一个一维数组。其内容是[100, 200)范围内的整数。

基本上, 我们可以通过array [index]指定下标来访问数组的元素。

# array_index.py

import numpy as np

base_data = np.arange(100, 200)
print("base_data\n={}\n".format(base_data))

print("base_data[10] = {}\n".format(base_data[10]))

上面代码的输出如下:

base_data
=[100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
 190 191 192 193 194 195 196 197 198 199]

base_data[10] = 110

在NumPy中, 我们可以创建一个包含多个下标的数组, 以获取目标数组中的元素。例如:

# array_index.py
every_five = np.arange(0, 100, 5)
print("base_data[every_five] = \n{}\n".format(
    base_data[every_five]))

every_five是包含我们要获取的下标的数组, 我们很容易理解代码。我们可以直接通过方括号获得指定下标的所有元素:

base_data[every_five] = 
[100 105 110 115 120 125 130 135 140 145 150 155 160 165 170 175 180 185
 190 195]

下标数组可以是一维或多维。假设我们要获得一个2X2矩阵, 其内容来自目标数组中1、2、10和20的四个下标, 因此可以编写代码:

# array_index.py
a = np.array([(1, 2), (10, 20)])
print("a = \n{}\n".format(a))
print("base_data[a] = \n{}\n".format(base_data[a]))

输出如下:

a = 
[[ 1  2]
 [10 20]]
 
base_data[a] = 
[[101 102]
 [110 120]]

我们看到的是目标数组是一维的情况。让我们将以下数组转换为10X10二维数组。

# array_index.py
base_data2 = base_data.reshape(10, -1)
print("base_data2 = np.reshape(base_data, (10, -1)) = \n{}\n".format(base_data2))

之前已经介绍了重塑功能, 结果如下:

base_data2 = np.reshape(base_data, (10, -1)) = 
[[100 101 102 103 104 105 106 107 108 109]
 [110 111 112 113 114 115 116 117 118 119]
 [120 121 122 123 124 125 126 127 128 129]
 [130 131 132 133 134 135 136 137 138 139]
 [140 141 142 143 144 145 146 147 148 149]
 [150 151 152 153 154 155 156 157 158 159]
 [160 161 162 163 164 165 166 167 168 169]
 [170 171 172 173 174 175 176 177 178 179]
 [180 181 182 183 184 185 186 187 188 189]
 [190 191 192 193 194 195 196 197 198 199]]

对于二维数组,

  • 如果我们仅指定一个下标, 则访问的结果仍然是一个数组。
  • 如果我们指定两个下标, 则访问的结果是其中的元素。
  • 我们还可以通过“ -1”指定最后一个元素。
# array_index.py
print("base_data2[2] = \n{}\n".format(base_data2[2]))
print("base_data2[2, 3] = \n{}\n".format(base_data2[2, 3]))
print("base_data2[-1, -1] = \n{}\n".format(base_data2[-1, -1]))

代码的输出如下。

对于高维数组, 原理是相同的, 你可以自己推理。

base_data2[2] = 
[120 121 122 123 124 125 126 127 128 129]

base_data2[2, 3] = 
123

base_data2[-1, -1] = 
199

另外, 我们还可以通过“:”指定范围, 例如:2:5。仅写“:”表示完整范围。

请参见下面的代码:

# array_index.py
print("base_data2[2, :]] = \n{}\n".format(base_data2[2, :]))
print("base_data2[:, 3]] = \n{}\n".format(base_data2[:, 3]))
print("base_data2[2:5, 2:4]] = \n{}\n".format(base_data2[2:5, 2:4]))

它会:

  1. 获取下标为2的行的所有元素
  2. 获取下标为3的列的所有元素
  3. 获取下标在[2, 5)中的行的所有元素以及下标在[2, 4)的列的所有元素。请仔细观察以下输出:
base_data2[2, :]] = 
[120 121 122 123 124 125 126 127 128 129]

base_data2[:, 3]] = 
[103 113 123 133 143 153 163 173 183 193]

base_data2[2:5, 2:4]] = 
[[122 123]
 [132 133]
 [142 143]]

7.数学

NumPy中还有很多数学函数。这里有些例子。有关更多功能, 请参见:NumPy手册内容

# operation.py

import numpy as np

base_data = (np.random.random((5, 5)) - 0.5) * 100
print("base_data = \n{}\n".format(base_data))

print("np.amin(base_data) = {}".format(np.amin(base_data)))
print("np.amax(base_data) = {}".format(np.amax(base_data)))
print("np.average(base_data) = {}".format(np.average(base_data)))
print("np.sum(base_data) = {}".format(np.sum(base_data)))
print("np.sin(base_data) = \n{}".format(np.sin(base_data)))

代码的输出如下:

base_data = 
[[ -9.63895991   6.9292461   -2.35654712 -48.45969283  13.56031937]
 [-39.75875796 -43.21031705 -49.27708561   6.80357128  33.71975059]
 [ 36.32228175  30.92546582 -41.63728955  28.68799187   6.44818484]
 [  7.71568596  43.24884701 -14.90716555  -9.24092252   3.69738718]
 [-31.90994273  34.06067289  18.47830413 -16.02495202 -44.84625246]]

np.amin(base_data) = -49.277085606595726
np.amax(base_data) = 43.24884701268845
np.average(base_data) = -3.22680706079886
np.sum(base_data) = -80.6701765199715
np.sin(base_data) = 
[[ 0.21254814  0.60204578 -0.70685739  0.9725159   0.8381861 ]
 [-0.88287359  0.69755541  0.83514527  0.49721505  0.74315189]
 [-0.98124746 -0.47103234  0.7149727  -0.40196147  0.16425187]
 [ 0.99045239 -0.66943662 -0.71791164 -0.18282139 -0.5276184 ]
 [-0.4741657   0.47665553 -0.36278223  0.31170676 -0.76041722]]

8.矩阵

现在, 让我们看一下如何以矩阵方式使用NumPy。

首先, 让我们创建一个5X5随机整数矩阵。有两种获取矩阵转置的方法:.T或转置函数。另外, 矩阵可以通过点函数相乘。示例代码如下:

# matrix.py

import numpy as np

base_data = np.floor((np.random.random((5, 5)) - 0.5) * 100)
print("base_data = \n{}\n".format(base_data))

print("base_data.T = \n{}\n".format(base_data.T))
print("base_data.transpose() = \n{}\n".format(base_data.transpose()))

matrix_one = np.ones((5, 5))
print("matrix_one = \n{}\n".format(matrix_one))

minus_one = np.dot(matrix_one, -1)
print("minus_one = \n{}\n".format(minus_one))

print("np.dot(base_data, minus_one) = \n{}\n".format(
    np.dot(base_data, minus_one)))

输出如下:

base_data = 
[[-49.  -5.  11. -13. -41.]
 [ -6. -33. -33. -47.  -4.]
 [-38.  26.  28. -18.  18.]
 [ -3. -19. -15. -39.  45.]
 [-43.   6.  18. -15. -21.]]

base_data.T = 
[[-49.  -6. -38.  -3. -43.]
 [ -5. -33.  26. -19.   6.]
 [ 11. -33.  28. -15.  18.]
 [-13. -47. -18. -39. -15.]
 [-41.  -4.  18.  45. -21.]]

base_data.transpose() = 
[[-49.  -6. -38.  -3. -43.]
 [ -5. -33.  26. -19.   6.]
 [ 11. -33.  28. -15.  18.]
 [-13. -47. -18. -39. -15.]
 [-41.  -4.  18.  45. -21.]]

matrix_one = 
[[ 1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.]]

minus_one = 
[[-1. -1. -1. -1. -1.]
 [-1. -1. -1. -1. -1.]
 [-1. -1. -1. -1. -1.]
 [-1. -1. -1. -1. -1.]
 [-1. -1. -1. -1. -1.]]

np.dot(base_data, minus_one) = 
[[  97.   97.   97.   97.   97.]
 [ 123.  123.  123.  123.  123.]
 [ -16.  -16.  -16.  -16.  -16.]
 [  31.   31.   31.   31.   31.]
 [  55.   55.   55.   55.   55.]]

9.随机数

在本文的结尾, 让我们看一下随机数的用法。

随机数是我们在编程过程中经常使用的功能, 例如生成演示数据或随机破坏现有数据序列以分割建模数据和验证数据。

numpy.random包包含许多用于随机数的算法。这里我们列出了四种最常见的用法:

# rand.py

import numpy as np

print("random: {}\n".format(np.random.random(20)));

print("rand: {}\n".format(np.random.rand(3, 4)));

print("randint: {}\n".format(np.random.randint(0, 100, 20)));

print("permutation: {}\n".format(np.random.permutation(np.arange(20))));

四种用法是:

  1. 生成20个随机数, 每个随机数在[0.0, 1.0)之间
  2. 根据指定形状生成随机数
  3. 生成指定范围(例如[0, 100))内指定数量(例如20)的随机整数
  4. 随机破坏现有数据的顺序([0, 1, 2, …, 19])

输出如下:

random: [0.62956026 0.56816277 0.30903156 0.50427765 0.92117724 0.43044905
 0.54591323 0.47286235 0.93241333 0.32636472 0.14692983 0.02163887
 0.85014782 0.20164791 0.76556972 0.15137427 0.14626625 0.60972522
 0.2995841  0.27569573]

rand: [[0.38629927 0.43779617 0.96276889 0.80018417]
 [0.67656892 0.97189483 0.13323458 0.90663724]
 [0.99440473 0.85197677 0.9420241  0.79598706]]

randint: [74 65 51 34 22 69 81 36 73 35 98 26 41 84  0 93 41  6 51 55]

permutation: [15  3  8 18 14 19 16  1  0  4 10 17  5  2  6 12  9 11 13  7]
赞(0)
未经允许不得转载:srcmini » NumPy教程:Python机器学习库

评论 抢沙发

评论前必须登录!