Scheme 矩阵运算

15 篇文章 0 订阅

Scheme 矩阵运算

基于 SICP 练习 2.37

引言

定义矩阵乘法的动机如下:

变换矩阵
线性变换矩阵
线性变换作用在向量上矩阵乘向量
线性变换叠加矩阵乘法

本文实现如下操作:

  • 向量点积
  • 矩阵乘向量
  • 矩阵乘矩阵

extend 和 reduce

后面会用到的两个函数。

连接表:

(define (extend seq1 seq2)
  (if (null? seq1)
      seq2
      (cons (car seq1)
            (extend (cdr seq1) seq2))))

左聚合,左折叠……这操作叫什么?

(define (reduce op seq)
  (define (iter r s)
    (if (null? s)
        r
        (iter (op r (car s)) (cdr s))))
  (iter (car seq) (cdr seq)))

Map Reduce

顺便说一下我对MapReduce的理解。

本来,对一批数据中的一行数据的处理就可能涉及该行本身或者涉及其他的行。而一旦一个处理涉及多行,它就很可能不能并行,比如求解线性方程组的高斯-赛德尔迭代法

而如果一个处理能被分成两部分,一个只涉及一行的局部处理和另一个涉及多行的汇总处理(一横一纵),即mapreduce,就可以把处理清晰地分为可并行与不可并行两部分。

向量点积

(define (dot v w)
  (reduce + (map * v w)))

从概念上讲,这里map并行处理v, w。

矩阵乘向量

[ x 1 x 2 x 3 x 4 ] [ y 1 y 2 ] = [ x 1 y 1 + x 2 y 2 x 3 y 1 + x 4 y 2 ] \left[ \begin{matrix} x_1 & x_2 \\ x_3 & x_4 \end{matrix} \right] \left[ \begin{matrix} y_1 \\ y_2 \end{matrix} \right]= \left[ \begin{matrix} x_1y_1+x_2y_2 \\ x_3y_1+x_4y_2 \end{matrix} \right] [x1x3x2x4][y1y2]=[x1y1+x2y2x3y1+x4y2]

可以看出,结果中的某一行的计算只涉及矩阵中同一行号的那一行。比如,结果的第一行中没有 x 3 x_3 x3 x 4 x_4 x4。所以我们可以对mat进行map

(define (matrix-*-vector mat v)
  (map (lambda (x) (dot x v)) mat))

map规则就是和v做点积。

矩阵转置

这个操作在 python 中很容易:

# 比如
> mat1
array([[1, 2, 3, 4],
       [4, 5, 6, 6],
       [6, 7, 8, 9]])

> list(zip(*mat1))    # attention!
array([[1, 4, 6],
       [2, 5, 7],
       [3, 6, 8],
       [4, 6, 9]])

怎么在 scheme 中做同样的事呢?需要费些心思:

(define (transpose mat)
  (reduce (lambda (x y) (map extend x y))
          (map (lambda (x) (map list x)) mat)))

这里有三个map,从上到下、从左到右解释一下:

  • x, y 是两个序列,用 extend 把 x, y 的同位元素连接起来。

    所谓同位元素,可以看一下例子:

    > (map + (list 1 2 3) (list 3 2 1))
    (4 4 4)
    
  • 对矩阵中的每一行做某种操作

  • 把 x 中的每个元素装到一个 list 里面。根据上下文,x 就是矩阵中的行。

所以整体的效果是这样的:

  • 将矩阵中的每一行中的每一个元素装到一个 list 里面
  • 启动 reduce 过程,将每行的同位元素(已经装到 list 里面了)连接起来,reduce 结果也是一个 list,其中的每个元素都是同位相连的结果。同位操作是靠 map 表达的。

再回头看一下 python:

list(zip(*mat1))

zip只是map的特例,关键是*,我还不知道怎么在 Scheme 中做同样的事。

矩阵乘矩阵

(define (matrix-*-matrix mat1 mat2)
  (define mat2t (transpose mat2))
  (map (lambda (row)
         (matrix-*-vector mat2t row))
       mat1))

观察矩阵相乘的过程,结果中的行恰是(矩阵乘法的)左操作数中的行右乘右操作数的转置。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值