白手起家学习数据科学 ——线性代数之“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
在其他章节中我们会用到关于矩阵的操作。
相关文章推荐
- Xcode如何关闭ARC
- androidstudio 中 使用git
- HashMap两种遍历方式的效率比较
- 从程序员到项目经理(7):程序员加油站 -- 不要死于直率
- 从程序员到项目经理(6):程序员加油站 -- 完美主义也是一种错
- ArcGIS10.3_解决属性表中文乱码问题
- javascript定义对象写法
- 【PMP考试难点辨析】质量管理三大过程剖析及易错题总结(丁仿)
- TRANSLATE 函数
- java从Eclipse的Console中读取数据(尤其汉字)遇到的问题
- Scrapy spiders介绍
- 获取对象的几种方式与构造函数Constructor的调用
- openv计时类TickMeter
- 各hbase版本对hadoop各版本的支持情况
- [javascript]DOM基础
- Java线程池介绍
- 从程序员到项目经理(5):程序员加油站 -- 懂电脑更要懂人脑
- 带连接池的netty客户端核心功能实现剖解
- 每天一个linux命令(50):crontab命令
- jsp内置对象作业2-留言簿