数据挖掘 numpy进阶之线性代数

简单数组运算

参考numpy文件夹中的linalg.py获得更多信息。

import numpy
import numpy.linalg as linalg
a = numpy.array([
    [1, 2],
    [3, 4]
], dtype=float)
print("a: \n", a)

print("a的转置: \n", a.transpose())
print("a的你矩阵: \n", linalg.inv(a))

u = numpy.eye(2)  # 2×2单位矩阵, eye = I
print("单位矩阵u: \n", u)
print("u的迹: \n", numpy.trace(u))
j = numpy.array([
    [0, -1],
    [1, 0]
], dtype=float)
print("j: \n", j)
print("j×j: \n", numpy.dot(j, j))  # 矩阵积

y = numpy.array([
    [5],
    [7]
], dtype=float)
print("y: \n", y)
print("线性方程求解: \n", linalg.solve(a, y))
print("特征向量求解: \n", linalg.eig(j))

"E:\Python 3.6.2\python.exe" F:/PycharmProjects/test.py
a: 
 [[ 1.  2.]
 [ 3.  4.]]
a的转置: 
 [[ 1.  3.]
 [ 2.  4.]]
a的你矩阵: 
 [[-2.   1. ]
 [ 1.5 -0.5]]
单位矩阵u: 
 [[ 1.  0.]
 [ 0.  1.]]
u的迹: 
 2.0
j: 
 [[ 0. -1.]
 [ 1.  0.]]
j×j: 
 [[-1.  0.]
 [ 0. -1.]]
y: 
 [[ 5.]
 [ 7.]]
线性方程求解: 
 [[-3.]
 [ 4.]]
特征向量求解: 
 (array([ 0.+1.j,  0.-1.j]), array([[ 0.70710678+0.j        ,  0.70710678-0.j        ],
       [ 0.00000000-0.70710678j,  0.00000000+0.70710678j]]))

Process finished with exit code 0

矩阵类

这是一个关于矩阵类的简短介绍。

import numpy
import numpy.linalg as linalg

a = numpy.matrix('1, 2; 3, 4', dtype=float)
print("a: \n", a)
print("TYPE a: ", type(a))

print("a的转置: \n", a.T)

x = numpy.matrix('5, 7', dtype=float).T
print("a×x: \n", a*x)

print("线性方程求解: \n", linalg.solve(a, x))
"E:\Python 3.6.2\python.exe" F:/PycharmProjects/test.py
a: 
 [[ 1.  2.]
 [ 3.  4.]]
TYPE a:  <class 'numpy.matrixlib.defmatrix.matrix'>
a的转置: 
 [[ 1.  3.]
 [ 2.  4.]]
a×x: 
 [[ 19.]
 [ 43.]]
线性方程求解: 
 [[-3.]
 [ 4.]]

Process finished with exit code 0

索引:比较矩阵和二维数组

注意NumPy中数组和矩阵有些重要的区别。

NumPy提供了两个基本的对象:

一个N维数组对象和一个通用函数对象。其它对象都是建构在它们之上 的。

特别的,矩阵是继承自NumPy数组对象的二维数组对象。

对数组和矩阵,索引都必须包含合适的一个或多个这些组合:整数标量、省略号 (ellipses)、整数列表;布尔值,整数或布尔值构成的元组,和一个一维整数或布尔值数组。

矩阵可以被用作矩阵的索引,但是通常需要数组、列表或者 其它形式来完成这个任务。

像平常在Python中一样,索引是从0开始的。传统上我们用矩形的行和列表示一个二维数组或矩阵,其中沿着0轴的方向被穿过的称作行,沿着1轴的方向被穿过的是列。

import numpy
import numpy.linalg as linalg

# 创建数组和矩阵用来切片

A = numpy.arange(12)
print("A :", A)
A.shape = 3, 4
M = numpy.mat(A.copy())  # 深复制,转成矩阵
print("TYPE A: {}, TYPE M: {}".format(type(A), type(M)))

print("A: \n", A)
print("M: \n", M)



"E:\Python 3.6.2\python.exe" F:/PycharmProjects/test.py
A : [ 0  1  2  3  4  5  6  7  8  9 10 11]
TYPE A: <class 'numpy.ndarray'>, TYPE M: <class 'numpy.matrixlib.defmatrix.matrix'>
A: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
M: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

Process finished with exit code 0

基本的切片使用切片对象或整数。例如A[ : ]、M[ : ]的求值将表现得和Python索引很相似。然而要注意很重要的一点就是NumPy切片数组不创建数据的副本;切片提供统一数据的视图。

>>> print A[:]; print A[:].shape
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
(3, 4)
>>> print M[:]; print M[:].shape
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
(3, 4)

使用逗号分割索引来沿着多个轴索引。

import numpy
import numpy.linalg as linalg
# 创建数组和矩阵用来切片

A = numpy.arange(12)
print("A :", A)
A.shape = 3, 4
M = numpy.mat(A.copy())  # 深复制,转成矩阵

print("A: \n", A)
print("M: \n", M)

# 对二维数组使用一个冒号产生一个一维数组,然而矩阵产生了一个二维矩阵。
print("A[:, 1]: {} TYPE A[:, 1]: {}".format(A[:, 1], A[:, 1].shape))
print("M[:, 1]: \n {} TYPE M[:, 1]: {}".format(M[:, 1], M[:, 1].shape))
"E:\Python 3.6.2\python.exe" F:/PycharmProjects/test.py
A : [ 0  1  2  3  4  5  6  7  8  9 10 11]
TYPE A: <class 'numpy.ndarray'>, TYPE M: <class 'numpy.matrixlib.defmatrix.matrix'>
A: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
M: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
A[:, 1]: [1 5 9] TYPE A[:, 1]: (3,)
M[:, 1]: 
 [[1]
 [5]
 [9]] TYPE M[:, 1]: (3, 1)

Process finished with exit code 0

对二维数组使用一个冒号产生一个一维数组,然而矩阵产生了一个二维矩阵。10例如,一个M[2,:]切片产生了一个形状为(1,4)的矩阵,相比之下,一个数组的切片总是产生一个最低可能维度11的数组。例如,如果C是一个三维数组,C[...,1]产生一个二维的数组而C[1,:,1]产生一个一维数组。从这时开始,如果相应的矩阵切片结果是相同的话,我们将只展示数组切片的结果。

import numpy
import numpy.linalg as linalg
# 创建数组和矩阵用来切片

A = numpy.arange(12)
print("A :", A)
A.shape = 3, 4
M = numpy.mat(A.copy())  # 深复制,转成矩阵

print("A: \n", A)
print("M: \n", M)

# 对二维数组使用一个冒号产生一个一维数组,然而矩阵产生了一个二维矩阵。
print("A[:, 1]: {} TYPE A[:, 1]: {}".format(A[:, 1], A[:, 1].shape))  # 切出的列
print("M[:, 1]: \n {} TYPE M[:, 1]: {}".format(M[:, 1], M[:, 1].shape))

print("A[1, :]: {} TYPE A[1, :]: {}".format(A[1, :], A[1, :].shape))  # 切出的行
print("M[1, :]: {} TYPE M[1, :]: {}".format(M[1, :], M[1, :].shape))


"E:\Python 3.6.2\python.exe" F:/PycharmProjects/test.py
A : [ 0  1  2  3  4  5  6  7  8  9 10 11]
A: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
M: 
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
A[:, 1]: [1 5 9] TYPE A[:, 1]: (3,)
M[:, 1]: 
 [[1]
 [5]
 [9]] TYPE M[:, 1]: (3, 1)
A[1, :]: [4 5 6 7] TYPE A[1, :]: (4,)
M[1, :]: [[4 5 6 7]] TYPE M[1, :]: (1, 4)


Process finished with exit code 0

数组的第一列和第三列,一种方法是使用列表切片: 

# 切出第一列和第三列(从0开始计数)
print("M[:, [1, 3]]: {} TYPE M[:, [1, 3]]: {}".format(M[:, [1, 3]], M[:, [1, 3]].shape))
M[:, [1, 3]]: [[ 1  3]
 [ 5  7]
 [ 9 11]] TYPE M[:, [1, 3]]: (3, 2)

稍微复杂点的方法是使用 take() 方法(method):

print("M[:, [1, 3]]:", M[:, ].take([1, 3], axis=1))

如果我们想跳过第一行,我们可以这样:

# 跳过第一行
print("跳过A的第一行进行切片: ", A[1:, ].take([1, 3], axis=1))
# 跳过第一行,矩阵向量积实现
print("跳过A的第一行进行切片: ", A[numpy.ix_((1, 2), (1, 3))])
跳过A的第一行进行切片:  [[ 5  7]
 [ 9 11]]
跳过A的第一行进行切片:  [[ 5  7]
 [ 9 11]]

现在让我们做些更复杂的。比如说我们想要保留第一行大于1的列。一种方法是创建布尔索引:

>>> A[0,:]>1
array([False, False, True, True], dtype=bool)
>>> A[:,A[0,:]>1]
array([[ 2,  3],
       [ 6,  7],
       [10, 11]])

但是索引矩阵没这么方便,它只会计算第一行。

>>> M[0,:]>1
matrix([[False, False, True, True]], dtype=bool)
>>> M[:,M[0,:]>1]
matrix([[2, 3]])  # 不知道为什么报错,IndexError: too many indices for array

这个过程的问题是用“矩阵切片”来切片产生一个矩阵,但是矩阵有A属性,它的值是数组呈现的。所以我们仅仅做以下替代:

>>> M[:,M.A[0,:]>1]
matrix([[ 2,  3],
        [ 6,  7],
        [10, 11]])

如果我们想要在矩阵两个方向有条件地切片,我们必须稍微调整策略,代之以:

>>> A[A[:,0]>2,A[0,:]>1]      # 只取结果矩阵的对角线
array([ 6, 11])
>>> M[M.A[:,0]>2,M.A[0,:]>1]
matrix([[ 6, 11]])

我们需要使用向量积ix_():

>>> A[ix_(A[:,0]>2,A[0,:]>1)]
array([[ 6,  7],
       [10, 11]])
>>> M[ix_(M.A[:,0]>2,M.A[0,:]>1)]
matrix([[ 6,  7],
        [10, 11]])
print(A[numpy.ix_(A[:, 0] > 2, A[0, :] > 1)])  # 等价于A[A[:, 0] > 2, :][:, A[0, :] > 1]

猜你喜欢

转载自my.oschina.net/gain/blog/1806209
今日推荐