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

来源:互联网 发布:java list json 转换 编辑:程序博客网 时间:2024/05/16 15:15

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 rowdef 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 friendsfriendships[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

在其他章节中我们会用到关于矩阵的操作。

0 0