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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值