您的位置:首页 > 其它

白手起家学习数据科学 ——线性代数之“Matrices篇”(二)

2015-11-25 10:56 435 查看

Matrices(矩阵)

matrix是一个二维数字的集合,在Python里我们可以在一个list中嵌套若干list来表示一个matrix。在内部中的这些list必须具有相同的长度,而且每个list表示matrix的一行。如果A是一个matrix,那么 A[i][j]表示A中第i行第j列的一个元素,按着数据的惯例,我们通常把大写字母表示矩阵,例如:

A = [[1, 2, 3], # A has 2 rows and 3 columns
[4, 5, 6]]

B = [[1, 2], # B has 3 rows and 2 columns
[3, 4],
[5, 6]]


notice:在数学里,通常把矩阵的第一行命名为“row 1”,第一列命名为“column1”。因为我们使用的是Pyhton语言的list,所以我们是以0索引为原点,我们把矩阵的第一行命名为“row 0”,并且第1列命名为“column 0”。

因为我们使用的是 list-of-lists的表示方法,我们可以这样计算矩阵A的行列数,len(A)表示矩阵A的行数,len(A[0])表示矩阵A的列数:

def shape(A):
num_rows = len(A)
num_cols = len(A[0]) if A else 0 # number of elements in first row
return num_rows, num_cols


如果一个矩阵有n行、k列,我们可以把它看成n*k矩阵,有的时候我们把n*k矩阵的每一行看成一个长度为k的向量,把每一列看成是长度为n的向量:

def get_row(A, i):
return A[i]             # A[i] is already the ith row

def get_column(A, j):
return [A_i[j]          # jth element of row A_i
for A_i in A]   # for each row A_i


我们想要根据指定大小产生矩阵元素的函数来创建一个矩阵,我们使用嵌套的list理解器(即for-in模式)来做这个:

def make_matrix(num_rows, num_cols, entry_fn):
"""returns a num_rows x num_cols matrix
whose (i,j)th entry is entry_fn(i, j)"""
return [[entry_fn(i, j) # given i, create a list
for j in range(num_cols)] # [entry_fn(i, 0), ... ]
for i in range(num_rows)] # create one list for each i


根据下面的函数,你能创建一个5*5的矩阵(对角线上的元素为1,其他是0):

def is_diagonal(i, j):
"""1's on the 'diagonal', 0's everywhere else"""
return 1 if i == j else 0

# [[1, 0, 0, 0, 0],
# [0, 1, 0, 0, 0],
# [0, 0, 1, 0, 0],
# [0, 0, 0, 1, 0],
# [0, 0, 0, 0, 1]]


因为下面的一些原因矩阵对我们来说是很重要的。

第一,我们使用矩阵表示由多个向量组成的数据集,即认为矩阵的每一行是一个向量。例如,如果你有1000个人的身高、体重和年龄的数据,你可以把他们组合成一个1000*3的矩阵:

data = [[70, 170, 40],
[65, 120, 26],
[77, 250, 19],
# ....
]


第二,我们能使用n*k矩阵表示一个线性方程以及把k维的向量映射到n维向量(PCA),这些技术和概念会涉及到矩阵操作。

第三,矩阵能够被用来表示二值关系,我们能创建一个矩阵A,其中如果node_i与node_j有关系,则A[i][j]为1,否则为0。有如下关系:

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


node_0与node_1有关系、node_0与node_2有关系,等等。

我们可以用如下矩阵表示friendships的关系:

# user 0 1 2 3 4 5 6 7 8 9
#
friendships = [[0, 1, 1, 0, 0, 0, 0, 0, 0, 0], # user 0
[1, 0, 1, 1, 0, 0, 0, 0, 0, 0], # user 1
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0], # user 2
[0, 1, 1, 0, 1, 0, 0, 0, 0, 0], # user 3
[0, 0, 0, 1, 0, 1, 0, 0, 0, 0], # user 4
[0, 0, 0, 0, 1, 0, 1, 1, 0, 0], # user 5
[0, 0, 0, 0, 0, 1, 0, 0, 1, 0], # user 6
[0, 0, 0, 0, 0, 1, 0, 0, 1, 0], # user 7
[0, 0, 0, 0, 0, 0, 1, 1, 0, 1], # user 8
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0]] # user 9


如果用户有很少的关系(即friendships里1很少、0很多),这就是一个极其没有效率的表示方法,因为你保存了许多无用的0值。然而,这种表示方法能够很快的查找2个node是否有联系,即直接查找矩阵,无需遍历整个矩阵查找:

friendships[0][2] == 1 # True, 0 and 2 are friends
friendships[0][8] == 1 # False, 0 and 8 are not friends


相似的,如果你想要查找一个node与其他node的关系,你只需要遍历所在node的行或者列:

friends_of_five = [i # only need
for i, is_friend in enumerate(friendships[5]) # to look at
if is_friend] # one row


在其他章节中我们会用到关于矩阵的操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: