矩阵是Madlib中数据的基本格式,通常是二维的。在Madlib中,数组的概念与向量类似,数组通常是一维的,是矩阵的一种特殊形式。

一、矩阵表示

MADlib为矩阵提供了两种表示形式:稠密和稀疏。

1. 稠密

矩阵被表示为一维数组的分布式集合,例如3x10的矩阵如下表:

 row_id |         row_vec
--------+-------------------------
   1    | {9,6,5,8,5,6,6,3,10,8}
   2    | {8,2,2,6,6,10,2,1,9,9}
   3    | {3,9,9,9,8,6,3,9,5,6}

2. 稀疏

使用行列下标指示矩阵中每一个非零项,例如:

 row_id | col_id | value
--------+--------+-------
      1 |      1 |     9
      1 |      5 |     6
      1 |      6 |     6
      2 |      1 |     8
      3 |      1 |     3
      3 |      2 |     9
      4 |      7 |     0

所有矩阵运算都以任一种表示形式工作。

二、矩阵运算

1. 数组运算

Madlib的数组运算模块提供了一组用C和SQL实现的基本数组操作,是几种需要快速数组操作的机器学习算法的支持模块。数组运算函数支持以下数字类型:

  • SMALLINT
  • INTEGER
  • BIGINT
  • REAL
  • DOUBLE PRECISION(FLOAT8)
  • NUMERIC(内部被转化为FLOAT8,可能丢失精度)

另外,array_unnest_2d_to_1d()函数还支持TEXT和VARCHAR数据类型。

(1)数组运算函数
        数组运算函数列表及功能描述如表1所示。

函数

描述

array_add()

两个数组相加,需要所有值非空,返回与输入相同的数据类型。

sum()

向量元素求和,需要所有值非空,返回与输入相同的数据类型。

array_sub()

两个数组相减,需要所有值非空,返回与输入相同的数据类型。

array_mult()

两个数组相乘,需要所有值非空,返回与输入相同的数据类型。

array_div()

两个数组相除,需要所有值非空,返回与输入相同的数据类型。

array_dot()

两个数组点积,需要所有值非空,返回与输入相同的数据类型。

array_contains()

检查一个数组是否包含另一个数组。如果右边数组中的每个非零元素都等于左边数组中相同下标的元素,函数返回TRUE。

array_max()

返回数组中的最大值,忽略空值,返回与输入相同的数据类型。

array_max_index()

返回数组中的最大值及其对应的下标,忽略空值,返回类型的格式为[max, index],其元素类型与输入类型相同。

array_min()

返回数组中的最小值,忽略空值,返回与输入相同的数据类型。

array_min_index()

返回数组中的最小值及其对应的下标,忽略空值,返回类型的格式为[min, index],其元素类型与输入类型相同。

array_sum()

返回数组中值的和,忽略空值,返回与输入相同的数据类型。

array_sum_big()

返回数组中值的和,忽略空值,返回FLOAT8类型。该函数的意思是当汇总值可能超出元素类型范围时,替换array_sum()。

array_abs_sum()

返回数组中绝对值的和,忽略空值,返回与输入相同的数据类型。

array_abs()

返回由数组元素的绝对值组成的新数组,需要所有值非空。

array_mean()

返回数组的均值,忽略空值。

array_stddev()

返回数组的标准差,忽略空值。

array_of_float()

该函数创建元素个数为参数值的FLOAT8数组,初始值为0.0。

array_of_bigint()

该函数创建元素个数为参数值的BIGINT数组,初始值为0。

array_fill()

该函数将数组每个元素设置为参数值。

array_filter()

该函数只保留输入数组中符合指定标量运算符的元素。要求是一维数组,并且所有值非空。返回与输入相同的数据类型。缺省时该函数移除所有0值。

array_scalar_mult()

该函数将一个数组作为输入,元素与第二个参数指定的标量值相乘,返回结果数组。需要所有值非空,返回与输入相同的数据类型。

array_scalar_add()

该函数将一个数组作为输入,元素与第二个参数指定的标量值相加,返回结果数组。需要所有值非空,返回与输入相同的数据类型。

array_sqrt()

返回由数组元素的平方根组成的数组,需要所有值非空。

array_pow()

该函数以数组和一个float8为输入,返回每个元素的乘幂(由第二个参数指定)组成的数组, 需要所有值非空。

array_square()

返回由数组元素的平方组成的数组,需要所有值非空。

normalize()

该函数规范化一个数组,使它的元素平方和为1。要求是一维数组,并且所有值非空。

表1

(2)数组运算示例
        建立一个数据表,包含两个整型数组列,并添加数据。

drop table if exists array_tbl;
create table array_tbl
( id integer,
  array1 integer[],
  array2 integer[]
);

insert into array_tbl values
( 1, '{1,2,3,4,5,6,7,8,9}', '{9,8,7,6,5,4,3,2,1}' ),
( 2, '{1,1,0,1,1,2,3,99,8}','{0,0,0,-5,4,1,1,7,6}' );

查询array1列的最小值、最大值、均值和标准差。

select id,
       madlib.array_min(array1),
       madlib.array_max(array1),
       madlib.array_min_index(array1),
       madlib.array_max_index(array1),
       madlib.array_mean(array1),
       madlib.array_stddev(array1)
  from array_tbl;

结果:

 id | array_min | array_max | array_min_index | array_max_index |    array_mean    |   array_stddev
----+-----------+-----------+-----------------+-----------------+------------------+------------------
  1 |         1 |         9 | {1,1}           | {9,9}           |                5 | 2.73861278752583
  2 |         0 |        99 | {0,3}           | {99,8}          | 12.8888888888889 | 32.3784050118457
(2 rows)

执行数组加减。

select id,
       madlib.array_add(array1,array2),
       madlib.array_sub(array1,array2)
  from array_tbl;

结果:

 id |          array_add           |        array_sub
----+------------------------------+-------------------------
  1 | {10,10,10,10,10,10,10,10,10} | {-8,-6,-4,-2,0,2,4,6,8}
  2 | {1,1,0,-4,5,3,4,106,14}      | {1,1,0,6,-3,1,2,92,2}
(2 rows)

执行数组乘除。不包含id=2的行,因为有除数为0,会报错ERROR:  division by zero is not allowed。

select id,
       madlib.array_mult(array1,array2),
       madlib.array_div(array1,array2)
  from array_tbl
 where 0 != all(array2);

结果:

 id |         array_mult         |      array_div
----+----------------------------+---------------------
  1 | {9,16,21,24,25,24,21,16,9} | {0,0,0,0,1,1,2,4,9}
(1 row)

计算数组的点积,并根据点积定义验证结果。

select id,
       madlib.array_dot(array1, array2),
       madlib.array_sum(madlib.array_mult(array1,array2))
  from array_tbl;

结果:

 id | array_dot | array_sum
----+-----------+-----------
  1 |       165 |       165
  2 |       745 |       745
(2 rows)

数组元素乘标量值3。

select id,
       array1,
       madlib.array_scalar_mult(array1,3)
  from array_tbl;

结果:

 id |        array1        |     array_scalar_mult
----+----------------------+---------------------------
  1 | {1,2,3,4,5,6,7,8,9}  | {3,6,9,12,15,18,21,24,27}
  2 | {1,1,0,1,1,2,3,99,8} | {3,3,0,3,3,6,9,297,24}
(2 rows)

构造一个包含9个元素的数组,每个元素值设置为1.3。

select madlib.array_fill(madlib.array_of_float(9), 1.3::float);

结果:

              array_fill
---------------------------------------
 {1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3}
(1 row)

将二维数组列展开为一维数组集合。array_unnest_2d_to_1d是madlib 1.11版本的新增的函数,用于将二维数组展开为一维数组。1.10版本并无次函数,但可以创建一个UDF实现。

create or replace function madlib.array_unnest_2d_to_1d(anyarray)
returns table(unnest_row_id int, unnest_result anyarray) as
$func$
select d1,array_agg(val)
  from (select $1[d1][d2] val,d1,d2
          from generate_series(array_lower($1,1), array_upper($1,1)) d1,
               generate_series(array_lower($1,2), array_upper($1,2)) d2
         order by d1,d2) t
 group by d1
$func$ language sql immutable;

之后就可以调用函数展开二维数组:

select id, (madlib.array_unnest_2d_to_1d(val)).*
  from (select 1::int as id, array[[1.3,2.0,3.2],[10.3,20.0,32.2]]::float8[][] as val
         union all
        select 2, array[[pi(),pi()/2],[2*pi(),pi()],[pi()/4,4*pi()]]::float8[][]) t
 order by 1,2;

结果:

 id | unnest_row_id |            unnest_result
----+---------------+--------------------------------------
  1 |             1 | {1.3,2,3.2}
  1 |             2 | {10.3,20,32.2}
  2 |             1 | {3.14159265358979,1.5707963267949}
  2 |             2 | {6.28318530717959,3.14159265358979}
  2 |             3 | {0.785398163397448,12.5663706143592}
(5 rows)

如果调用函数时不用.*标记,函数将返回具有两个属性(行ID和对应的展开后一维数组)的复合记录类型。

2. 矩阵运算

矩阵运算函数支持的数据类型包括SMALLINT、INTEGER、BIGINT、FLOAT8和NUMERIC(内部被转化为FLOAT8,可能丢失精度),

(1)矩阵运算函数分类
        可大致分成以下类型:

  • 表示函数:

—— 转化为稀疏矩阵
matrix_sparsify( matrix_in, in_args, matrix_out, out_args)
—— 转化为稠密矩阵
matrix_densify( matrix_in, in_args, matrix_out, out_args)
—— 获取矩阵的维度 
matrix_ndims( matrix_in, in_args )

  • 算数函数:

-- 矩阵转置
matrix_trans( matrix_in, in_args, matrix_out, out_args)
-- 矩阵相加
matrix_add( matrix_a, a_args, matrix_b, b_args, matrix_out, out_args)
-- 矩阵相减
matrix_sub( matrix_a, a_args, matrix_b, b_args, matrix_out, out_args)
-- 矩阵乘法
matrix_mult( matrix_a, a_args, matrix_b, b_args, matrix_out, out_args)
-- 数组元素依次相乘
matrix_elem_mult( matrix_a, a_args, matrix_b, b_args, matrix_out, out_args)
-- 标量乘矩阵
matrix_scalar_mult( matrix_in, in_args, scalar, matrix_out, out_args)
-- 向量乘矩阵
matrix_vec_mult( matrix_in, in_args, vector)

  • 提取函数:

-- 从行下标提取行
matrix_extract_row( matrix_in, in_args, index)
-- 从列下标提取列
matrix_extract_col( matrix_in, in_args, index)
-- 提取主对角线元素
matrix_extract_diag( matrix_in, in_args)

  • 规约函数(跨指定维度的聚合):

-- 获取维度最大值。如果fetch_index = True,返回对应的下标。
matrix_max( matrix_in, in_args, dim, matrix_out, fetch_index)
-- 获取维度最小值。如果fetch_index = True,返回对应的下标。
matrix_min( matrix_in, in_args, dim, matrix_out, fetch_index)
-- 获取维度的和
matrix_sum( matrix_in, in_args, dim)
-- 获取维度的均值
matrix_mean( matrix_in, in_args, dim)
-- 获取矩阵范数
matrix_norm( matrix_in, in_args, norm_type)

  • 创建函数:

-- 创建一个指定矩阵,用1初始化为给定的行列维度。
matrix_ones( row_dim, col_dim, matrix_out, out_args)
-- 创建一个指定矩阵,用0初始化为给定的行列维度。
matrix_zeros( row_dim, col_dim, matrix_out, out_args)
-- 创建正方形恒等矩阵
matrix_identity( dim, matrix_out, out_args)
-- 用给定对角元素初始化矩阵
matrix_diag( diag_elements, matrix_out, out_args)
-- 用从分布中采样的值初始化矩阵。支持普通、均匀、伯努利分布
matrix_random( distribution, row_dim, col_dim, in_args, matrix_out, out_args )

  • 分解函数:

-- 矩阵求逆
matrix_inverse( matrix_in, in_args, matrix_out, out_args)
-- 广义逆矩阵
matrix_pinv( matrix_in, in_args, matrix_out, out_args)
-- 矩阵特征提取
matrix_eigen( matrix_in, in_args, matrix_out, out_args)
-- Cholesky分解
matrix_cholesky( matrix_in, in_args, matrix_out_prefix, out_args)
-- QR分解
matrix_qr( matrix_in, in_args, matrix_out_prefix, out_args)
-- LU分解
matrix_lu( matrix_in, in_args, matrix_out_prefix, out_args)
-- 矩阵的核范数
matrix_nuclear_norm( matrix_in, in_args)
-- 矩阵的秩
matrix_rank( matrix_in, in_args)

        分解函数仅基于内存操作实现。单一节点的矩阵数据被用于分解计算。这种操作适合小型矩阵,因为计算不是分布到个多个节点的。

(2)稠密矩阵运算示例
        创建实例稠密矩阵表和数据。

drop table if exists mat_a;
create table mat_a (
        row_id integer,
        row_vec integer[]
);
insert into mat_a (row_id, row_vec) values (1, '{9,6,5,8,5,6,6,3,10,8}');
insert into mat_a (row_id, row_vec) values (2, '{8,2,2,6,6,10,2,1,9,9}');
insert into mat_a (row_id, row_vec) values (3, '{3,9,9,9,8,6,3,9,5,6}');
insert into mat_a (row_id, row_vec) values (4, '{6,4,2,2,2,7,8,8,0,7}');
insert into mat_a (row_id, row_vec) values (5, '{6,8,9,9,4,6,9,5,7,7}');
insert into mat_a (row_id, row_vec) values (6, '{4,10,7,3,9,5,9,2,3,4}');
insert into mat_a (row_id, row_vec) values (7, '{8,10,7,10,1,9,7,9,8,7}');
insert into mat_a (row_id, row_vec) values (8, '{7,4,5,6,2,8,1,1,4,8}');
insert into mat_a (row_id, row_vec) values (9, '{8,8,8,5,2,6,9,1,8,3}');
insert into mat_a (row_id, row_vec) values (10, '{4,6,3,2,6,4,1,2,3,8}');

drop table if exists mat_b;
create table mat_b (
    row_id integer,
    vector integer[]
);
insert into mat_b (row_id, vector) values (1, '{9,10,2,4,6,5,3,7,5,6}');
insert into mat_b (row_id, vector) values (2, '{5,3,5,2,8,6,9,7,7,6}');
insert into mat_b (row_id, vector) values (3, '{0,1,2,3,2,7,7,3,10,1}');
insert into mat_b (row_id, vector) values (4, '{2,9,0,4,3,6,8,6,3,4}');
insert into mat_b (row_id, vector) values (5, '{3,8,7,7,0,5,3,9,2,10}');
insert into mat_b (row_id, vector) values (6, '{5,3,1,7,6,3,5,3,6,4}');
insert into mat_b (row_id, vector) values (7, '{4,8,4,4,2,7,10,0,3,3}');
insert into mat_b (row_id, vector) values (8, '{4,6,0,1,3,1,6,6,9,8}');
insert into mat_b (row_id, vector) values (9, '{6,5,1,7,2,7,10,6,0,6}');
insert into mat_b (row_id, vector) values (10, '{1,4,4,4,8,5,2,8,5,5}');

矩阵转置。

select madlib.matrix_trans('"mat_b"', 'row=row_id, val=vector','mat_r');
select * from mat_r order by row_id;

结果:

 row_id |         vector
--------+-------------------------
      1 | {9,5,0,2,3,5,4,4,6,1}
      2 | {10,3,1,9,8,3,8,6,5,4}
      3 | {2,5,2,0,7,1,4,0,1,4}
      4 | {4,2,3,4,7,7,4,1,7,4}
      5 | {6,8,2,3,0,6,2,3,2,8}
      6 | {5,6,7,6,5,3,7,1,7,5}
      7 | {3,9,7,8,3,5,10,6,10,2}
      8 | {7,7,3,6,9,3,0,6,6,8}
      9 | {5,7,10,3,2,6,3,9,0,5}
     10 | {6,6,1,4,10,4,3,8,6,5}
(10 rows)

提取矩阵的主对角线。

select madlib.matrix_extract_diag('mat_b', 'row=row_id, val=vector');

结果:

  matrix_extract_diag
------------------------
 {9,3,2,4,0,3,10,6,0,5}
(1 row)

矩阵相加。

drop table if exists mat_r;
select madlib.matrix_add('mat_a', 'row=row_id, val=row_vec',
                         'mat_b', 'row=row_id, val=vector',
                         'mat_r', 'val=vector, fmt=dense');
select * from mat_r order by row_id;

结果:

 row_id |            vector
--------+-------------------------------
      1 | {18,16,7,12,11,11,9,10,15,14}
      2 | {13,5,7,8,14,16,11,8,16,15}
      3 | {3,10,11,12,10,13,10,12,15,7}
      4 | {8,13,2,6,5,13,16,14,3,11}
      5 | {9,16,16,16,4,11,12,14,9,17}
      6 | {9,13,8,10,15,8,14,5,9,8}
      7 | {12,18,11,14,3,16,17,9,11,10}
      8 | {11,10,5,7,5,9,7,7,13,16}
      9 | {14,13,9,12,4,13,19,7,8,9}
     10 | {5,10,7,6,14,9,3,10,8,13}
(10 rows)

矩阵相乘。

drop table if exists mat_r;
select madlib.matrix_mult('mat_a', 'row=row_id, val=row_vec',
                          'mat_b', 'row=row_id, val=vector, trans=true',
                          'mat_r');
select * from mat_r order by row_id;

结果:

 row_id |                  row_vec
--------+-------------------------------------------
      1 | {380,373,251,283,341,303,302,309,323,281}
      2 | {318,318,222,221,269,259,236,249,264,248}
      3 | {382,366,216,300,397,276,277,270,313,338}
      4 | {275,284,154,244,279,183,226,215,295,204}
      5 | {381,392,258,319,394,298,342,302,360,300}
      6 | {321,333,189,276,278,232,300,236,281,250}
      7 | {443,411,282,365,456,318,360,338,406,330}
      8 | {267,240,150,186,270,194,210,184,233,193}
      9 | {322,328,234,264,291,245,317,253,291,219}
     10 | {246,221,109,173,222,164,167,185,181,189}
(10 rows)

创建对角矩阵。

drop table if exists mat_r;
select madlib.matrix_diag(array[9,6,3,10],
                          'mat_r', 'row=row_id, col=col_id, val=val');
select * from mat_r order by row_id::bigint;

结果:

 row_id | col_id | val
--------+--------+-----
      1 |      1 |   9
      2 |      2 |   6
      3 |      3 |   3
      4 |      4 |  10
(4 rows)

创建单位矩阵。

drop table if exists mat_r;
select madlib.matrix_identity(4, 'mat_r', 'row=row_id,col=col_id,val=val');
select * from mat_r order by row_id;

结果:

 row_id | col_id | val
--------+--------+-----
      1 |      1 |   1
      2 |      2 |   1
      3 |      3 |   1
      4 |      4 |   1
(4 rows)

提取指定下标的行或列。

select madlib.matrix_extract_row('mat_a', 'row=row_id, val=row_vec', 2) as row,
       madlib.matrix_extract_col('mat_a', 'row=row_id, val=row_vec', 3) as col;

结果:

          row           |          col
------------------------+-----------------------
 {8,2,2,6,6,10,2,1,9,9} | {5,2,9,2,9,7,7,5,8,3}
(1 row)

获取指定维度的最大最小值及其对应的下标。dim=2表示计算每一行的最大最小值,返回一个列向量。

drop table if exists mat_max_r;
drop table if exists mat_min_r;
select madlib.matrix_max('mat_a', 'row=row_id, val=row_vec', 2, 'mat_max_r', true),
       madlib.matrix_min('mat_a', 'row=row_id, val=row_vec', 2, 'mat_min_r', true);
select * from mat_max_r;
select * from mat_min_r;

结果:

         index          |            max
------------------------+---------------------------
 {9,6,2,7,3,2,2,6,7,10} | {10,10,9,8,9,10,10,8,9,8}
(1 row)

         index         |          min
-----------------------+-----------------------
 {8,8,1,9,5,8,5,7,8,7} | {3,1,3,0,4,2,1,1,1,1}
(1 row)

用稀疏格式初始化矩阵。

drop table if exists mat_r;
select madlib.matrix_zeros(5, 4, 'mat_r', 'row=row_id, col=col_id, val=entry');
select * from mat_r;

结果:

 row_id | col_id | entry
--------+--------+-------
      5 |      4 |     0
(1 row)

用稠密格式初始化矩阵。

drop table if exists mat_r;
select madlib.matrix_zeros(5, 4, 'mat_r', 'fmt=dense');
select * from mat_r order by row;

结果:

 row |    val
-----+-----------
   1 | {0,0,0,0}
   2 | {0,0,0,0}
   3 | {0,0,0,0}
   4 | {0,0,0,0}
   5 | {0,0,0,0}
(5 rows)

用1初始化矩阵。

drop table if exists mat_r;
select madlib.matrix_ones(5, 4, 'mat_r', 'row=row,col=col, val=val');
select * from mat_r order by row, col;

结果:

 row | col | val
-----+-----+-----
   1 |   1 |   1
   1 |   2 |   1
   1 |   3 |   1
   1 |   4 |   1
   2 |   1 |   1
   2 |   2 |   1
   2 |   3 |   1
   2 |   4 |   1
   3 |   1 |   1
   3 |   2 |   1
   3 |   3 |   1
   3 |   4 |   1
   4 |   1 |   1
   4 |   2 |   1
   4 |   3 |   1
   4 |   4 |   1
   5 |   1 |   1
   5 |   2 |   1
   5 |   3 |   1
   5 |   4 |   1
(20 rows)

用1初始化稠密矩阵。

drop table if exists mat_r;
select madlib.matrix_ones(5, 4, 'mat_r', 'fmt=dense');
select * from mat_r order by row;

结果:

 row |    val
-----+-----------
   1 | {1,1,1,1}
   2 | {1,1,1,1}
   3 | {1,1,1,1}
   4 | {1,1,1,1}
   5 | {1,1,1,1}
(5 rows)

两个矩阵元素相乘。

drop table if exists mat_r;
select madlib.matrix_elem_mult('mat_a', 'row=row_id, val=row_vec',
                               'mat_b', 'row=row_id, val=vector',
                               'mat_r', 'val=vector');
select * from mat_r order by row_id;

结果:

 row_id |             vector
--------+---------------------------------
      1 | {81,60,10,32,30,30,18,21,50,48}
      2 | {40,6,10,12,48,60,18,7,63,54}
      3 | {0,9,18,27,16,42,21,27,50,6}
      4 | {12,36,0,8,6,42,64,48,0,28}
      5 | {18,64,63,63,0,30,27,45,14,70}
      6 | {20,30,7,21,54,15,45,6,18,16}
      7 | {32,80,28,40,2,63,70,0,24,21}
      8 | {28,24,0,6,6,8,6,6,36,64}
      9 | {48,40,8,35,4,42,90,6,0,18}
     10 | {4,24,12,8,48,20,2,16,15,40}
(10 rows)

按维度求和,本例中每行求和。

select madlib.matrix_sum('mat_a', 'row=row_id, val=row_vec', 2);

结果:

           matrix_sum
---------------------------------
 {66,55,67,46,70,56,76,46,58,39}
(1 row)

获取维度均值。

select madlib.matrix_mean('mat_a', 'row=row_id, val=row_vec', 2);

结果:

               matrix_mean
-----------------------------------------
 {6.6,5.5,6.7,4.6,7,5.6,7.6,4.6,5.8,3.9}
(1 row)

计算矩阵范数,本例求欧几里德范数。

select madlib.matrix_norm('mat_a', 'row=row_id, val=row_vec', '2');

结果:

  matrix_norm
---------------
 64.1014820421
(1 row)

标量乘矩阵。

drop table if exists mat_r;
select madlib.matrix_scalar_mult('mat_a', 'row=row_id, val=row_vec', 3, 'mat_r');
select * from mat_r order by row_id;

结果:

 row_id |             row_vec
--------+---------------------------------
      1 | {27,18,15,24,15,18,18,9,30,24}
      2 | {24,6,6,18,18,30,6,3,27,27}
      3 | {9,27,27,27,24,18,9,27,15,18}
      4 | {18,12,6,6,6,21,24,24,0,21}
      5 | {18,24,27,27,12,18,27,15,21,21}
      6 | {12,30,21,9,27,15,27,6,9,12}
      7 | {24,30,21,30,3,27,21,27,24,21}
      8 | {21,12,15,18,6,24,3,3,12,24}
      9 | {24,24,24,15,6,18,27,3,24,9}
     10 | {12,18,9,6,18,12,3,6,9,24}
(10 rows)

获取矩阵的行列维度数。

select madlib.matrix_ndims('"mat_a"', 'row=row_id, val=row_vec');

结果:

 matrix_ndims
--------------
 {10,10}
(1 row)

向量乘矩阵。

select madlib.matrix_vec_mult('mat_a', 'row=row_id, val=row_vec', array[1,2,3,4,5,6,7,8,9,10]);

结果:

              matrix_vec_mult
-------------------------------------------
 {365,325,358,270,377,278,411,243,287,217}
(1 row)

求逆矩阵。

drop table if exists mat_r;
select madlib.matrix_inverse('mat_a', 'row=row_id, val=row_vec', 'mat_r');
select row_vec from mat_r order by row_id;

求广义逆矩阵。

drop table if exists mat_r;
select madlib.matrix_pinv('mat_a', 'row=row_id, val=row_vec', 'mat_r');
select row_vec from mat_r order by row_id;

提取矩阵的特征值。

drop table if exists mat_r;
select madlib.matrix_eigen('mat_a', 'row=row_id, val=row_vec', 'mat_r');
select eigen_values from mat_r order by row_id;

矩阵的Cholesky分解。

select madlib.matrix_cholesky('mat_a', 'row=row_id, val=row_vec', 'matrix_out_prefix');
select row_vec from matrix_out_prefix_p order by row_id;
select row_vec from matrix_out_prefix_l order by row_id;
select row_vec from matrix_out_prefix_d order by row_id;

矩阵的QR分解。

select madlib.matrix_qr('mat_a', 'row=row_id, val=row_vec', 'matrix_out_prefix');
select row_vec from matrix_out_prefix_q order by row_id;
select row_vec from matrix_out_prefix_r order by row_id;

矩阵的LU分解。

select madlib.matrix_lu('mat_a', 'row=row_id, val=row_vec', 'matrix_out_prefix');
select row_vec from matrix_out_prefix_l order by row_id;
select row_vec from matrix_out_prefix_u order by row_id;
select row_vec from matrix_out_prefix_p order by row_id;
select row_vec from matrix_out_prefix_q order by row_id;

求矩阵的核范数。

select madlib.matrix_nuclear_norm('"mat_a"', 'row=row_id, val=row_vec');

结果:

 matrix_nuclear_norm
---------------------
       118.852685995
(1 row)

求矩阵的秩。

select madlib.matrix_rank('mat_a', 'row=row_id, val=row_vec');

结果:

 matrix_rank
-------------
          10
(1 row)

(3)稀疏矩阵运算示例
        稠密矩阵转为稀疏矩阵。

drop table if exists mat_b_sparse;
select madlib.matrix_sparsify('mat_b', 'row=row_id, val=vector',
                              'mat_b_sparse', 'col=col_id, val=val');
select * from mat_b_sparse order by row_id, col_id;

创建稀疏矩阵表及其数据。

drop table if exists mat_a_sparse;
create table mat_a_sparse (
    rownum integer,
    col_num integer,
    entry integer
);
insert into mat_a_sparse values (1, 1, 9);
insert into mat_a_sparse values (1, 2, 6);
insert into mat_a_sparse values (1, 7, 3);
insert into mat_a_sparse values (1, 8, 10);
insert into mat_a_sparse values (1, 9, 8);
insert into mat_a_sparse values (2, 1, 8);
insert into mat_a_sparse values (2, 2, 2);
insert into mat_a_sparse values (2, 3, 6);
insert into mat_a_sparse values (3, 5, 6);
insert into mat_a_sparse values (3, 6, 3);
insert into mat_a_sparse values (7, 1, 7);
insert into mat_a_sparse values (8, 2, 8);
insert into mat_a_sparse values (8, 3, 5);
insert into mat_a_sparse values (9, 1, 6);
insert into mat_a_sparse values (9, 2, 3);
insert into mat_a_sparse values (10, 10, 0);

获取行列维度数。

select madlib.matrix_ndims('mat_a_sparse', 'row="rownum", val=entry');

结果:

 matrix_ndims
--------------
 {10,10}
(1 row)

矩阵转置。

drop table if exists matrix_r_sparse;
select madlib.matrix_trans('mat_a_sparse', 'row=rownum, val=entry',
                           'matrix_r_sparse');
select rownum, col_num, entry from matrix_r_sparse order by col_num, rownum;

结果:

 rownum | col_num | entry
--------+---------+-------
      1 |       1 |     9
      2 |       1 |     6
      7 |       1 |     3
      8 |       1 |    10
      9 |       1 |     8
      1 |       2 |     8
      2 |       2 |     2
      3 |       2 |     6
      5 |       3 |     6
      6 |       3 |     3
      1 |       7 |     7
      2 |       8 |     8
      3 |       8 |     5
      1 |       9 |     6
      2 |       9 |     3
     10 |      10 |     0
(16 rows)

获取矩阵的主对角线。

select madlib.matrix_extract_diag('mat_a_sparse', 'row=rownum, val=entry');

结果:

  matrix_extract_diag
-----------------------
 {9,2,0,0,0,0,0,0,0,0}
(1 row)

添加两个稀疏矩阵,然后转换成稠密格式。

drop table if exists matrix_r_sparse;
drop table if exists matrix_r;
select madlib.matrix_add('mat_a_sparse', 'row=rownum, val=entry',
                         'mat_b_sparse', 'row=row_id, col=col_id, val=val',
                         'matrix_r_sparse', 'col=col_out');
select madlib.matrix_densify('matrix_r_sparse', 'row=rownum, col=col_out, val=entry',
                             'matrix_r');
select * from matrix_r order by rownum;

结果:

 rownum |           entry
--------+---------------------------
      1 | {18,16,2,4,6,5,6,17,13,6}
      2 | {13,5,11,2,8,6,9,7,7,6}
      3 | {0,1,2,3,8,10,7,3,10,1}
      4 | {2,9,0,4,3,6,8,6,3,4}
      5 | {3,8,7,7,0,5,3,9,2,10}
      6 | {5,3,1,7,6,3,5,3,6,4}
      7 | {11,8,4,4,2,7,10,0,3,3}
      8 | {4,14,5,1,3,1,6,6,9,8}
      9 | {12,8,1,7,2,7,10,6,0,6}
     10 | {1,4,4,4,8,5,2,8,5,5}
(10 rows)

矩阵相乘。

drop table if exists matrix_r;
select madlib.matrix_mult('mat_a_sparse', 'row=rownum, col=col_num, val=entry',
                          'mat_b_sparse', 'row=row_id, col=col_id, val=val, trans=true',
                          'matrix_r');
select * from matrix_r order by rownum;

结果:

 rownum |                   entry
--------+-------------------------------------------
      1 | {260,216,137,180,190,156,138,222,174,159}
      2 | {104,76,14,34,82,52,72,44,64,40}
      3 | {51,66,33,36,15,45,33,21,33,63}
      4 | {0,0,0,0,0,0,0,0,0,0}
      5 | {0,0,0,0,0,0,0,0,0,0}
      6 | {0,0,0,0,0,0,0,0,0,0}
      7 | {63,35,0,14,21,35,28,28,42,7}
      8 | {90,49,18,72,99,29,84,48,45,52}
      9 | {84,39,3,39,42,39,48,42,51,18}
     10 | {0,0,0,0,0,0,0,0,0,0}
(10 rows)

计算矩阵的Euclidean范数。

select madlib.matrix_norm('mat_a_sparse', 'row=rownum, col=col_num, val=entry', '2');

结果:

  matrix_norm
---------------
 24.9399278267
(1 row)

HAWQ + MADlib 玩转数据挖掘之(二)——矩阵的更多相关文章

  1. HAWQ + MADlib 玩转数据挖掘之(四)——低秩矩阵分解实现推荐算法

    一.潜在因子(Latent Factor)推荐算法 本算法整理自知乎上的回答@nick lee.应用领域:"网易云音乐歌单个性化推荐"."豆瓣电台音乐推荐"等. ...

  2. HAWQ + MADlib 玩转数据挖掘之(五)——奇异值分解实现推荐算法

    一.奇异值分解简介 奇异值分解简称SVD(singular value decomposition),可以理解为:将一个比较复杂的矩阵用更小更简单的三个子矩阵的相乘来表示,这三个小矩阵描述了大矩阵重要 ...

  3. HAWQ + MADlib 玩转数据挖掘之(一)——安装

    一.MADlib简介 MADlib是Pivotal公司与伯克利大学合作的一个开源机器学习库,提供了精确的数据并行实现.统计和机器学习方法对结构化和非结构化数据进行分析,主要目的是扩展数据库的分析能力, ...

  4. HAWQ + MADlib 玩转数据挖掘之(七)——关联规则方法之Apriori算法

    一.关联规则简介 关联规则挖掘的目标是发现数据项集之间的关联关系,是数据挖据中一个重要的课题.关联规则最初是针对购物篮分析(Market Basket Analysis)问题提出的.假设超市经理想更多 ...

  5. HAWQ + MADlib 玩转数据挖掘之(六)——主成分分析与主成分投影

    一.主成分分析(Principal Component Analysis,PCA)简介 在数据挖掘中经常会遇到多个变量的问题,而且在多数情况下,多个变量之间常常存在一定的相关性.例如,网站的" ...

  6. HAWQ + MADlib 玩转数据挖掘之(三)——向量

    一.定义 这里不讨论向量严格的数学定义.在Madlib中,可以把向量简单理解为矩阵.矩阵是Madlib中数据的基本格式,当矩阵只有一维时,就是向量,1行n列的矩阵称为行向量,m行1列的矩阵称为列向量, ...

  7. 菜鸟玩云计算之十二:KVM虚拟机更改大小

    菜鸟玩云计算之十二:KVM虚拟机更改大小 参考: http://www.missionfamilybank.org/expanding-resizing-your-qcow2-virtual-mach ...

  8. 用SQL玩转数据挖掘之MADlib(一)——安装

    一.MADlib简介 MADlib是Pivotal公司与伯克利大学合作的一个开源机器学习库,提供了精确的数据并行实现.统计和机器学习方法对结构化和非结构化数据进行分析,主要目的是扩展数据库的分析能力, ...

  9. BZOJ3577:玩手机(最大流,二维ST表)

    Description 现在有一堆手机放在坐标网格里面(坐标从1开始),坐标(i,j)的格子有s_(i,j)个手机. 玩手机当然需要有信号,不过这里的手机与基站与我们不太一样.基站分为两种:发送站和接 ...

随机推荐

  1. 20145322《Java程序设计》第3次实验报告

    实验内容,, 组队使用 git 上传代码并且互相下载对方代码修改之后再上传. 实现代码的重载 一. 使用git 上传代码 过程如图: 仨人成功上传后的代码图如下: 使用git 相互更改代码 执行git ...

  2. IO多路复用客户端-服务器模型

    IO多路复用服务器 -- 实现字符回射 服务器端 /************************************************************************* ...

  3. #ifndef用法

    用于避免重复包含头文件 #ifndef _STDIO_H_ #define _STDIO_H_ ...... #endif

  4. layer弹出层的关闭及父页面的刷新问题

    当在主页面执行添加或修改时,用弹出层是比较好的选择,如何关闭弹出层并对父级页面进行操作呢 首先在父级页面中打开一个添加页面(弹出层) 在添加页面的表单提交函数中添加如下代码: function for ...

  5. C# Nginx平滑加权轮询算法

    代码很简单,但算法很经典,话不多说,直接上代码. public struct ServerConfig { /// <summary> /// 初始权重 /// </summary& ...

  6. 【链接】SpringBoot启动错误

    [错误解决]SpringBoot启动错误 https://blog.csdn.net/Small_Mouse0/article/details/78551900

  7. STL的其他用法(adjacent_find, find_first_of, sort_heap, merge, binary_search)总结

    2017-08-20 17:26:07 writer:pprp 1.adjacent_find() 下面是源码实现: template <class ForwardIterator> Fo ...

  8. linux下增加useradd提示existing lock file /etc/subgid.lock without a PID

    # useradd git -g git useradd: existing lock file /etc/subgid.lock without a PID useradd: cannot lock ...

  9. url传递数据类型

    php中传递数据,get或post方式为啥用字符串传递,为什么不能直接用数组形式,用的话可以吗

  10. css实现标题文字过长截取...

    css实现网页中文字过长截取... title class应该这样写: .title{ width:300px; white-space:nowrap; overflow:hidden; text-o ...