데이터 타입 - RDD 기반 API

데이터 타입 - RDD 기반 API (Data Types – RDD-based API)

MLlib은 단일 머신에 저장되는 로컬 벡터(local vector)와 로컬 행렬(local matrix), 그리고 하나 이상의 RDD로 뒷받침되는 분산 행렬(distributed matrix)을 지원해요. 머신러닝에서 밥 먹듯 만나게 될 기본 데이터 타입들을 정리해 두었으니, 벡터와 행렬을 다루는 방법을 차근차근 익혀봅시다. 실제 선형대수 연산은 Breeze가 제공해요.

출처: 문서

본문

목차 (Table of Contents)

MLlib은 단일 머신에 저장되는 로컬 벡터와 로컬 행렬, 그리고 하나 이상의 RDD로 뒷받침되는 분산 행렬을 지원해요. 로컬 벡터와 로컬 행렬은 공개 인터페이스 역할을 하는 단순한 데이터 모델입니다. 기본 선형대수 연산은 Breeze가 제공해요. 지도 학습(supervised learning)에 사용되는 훈련 예제는 MLlib에서 "레이블된 포인트(labeled point)"라고 불러요.

로컬 벡터 (Local vector)

로컬 벡터는 정수 타입의 0-기반 인덱스와 double 타입 값을 가지며, 단일 머신에 저장됩니다. MLlib은 조밀(dense) 벡터와 희소(sparse) 벡터 두 가지 로컬 벡터 타입을 지원해요. 조밀 벡터는 항목 값을 나타내는 double 배열로 뒷받침되고, 희소 벡터는 인덱스와 값 두 개의 병렬 배열로 뒷받침됩니다. 예를 들어 벡터 (1.0, 0.0, 3.0)은 조밀 형식으로 [1.0, 0.0, 3.0], 희소 형식으로 (3, [0, 2], [1.0, 3.0])로 나타낼 수 있어요. 여기서 3은 벡터의 크기입니다.

Python:

MLlib은 다음 타입을 조밀 벡터로 인식해요:
- NumPy의 [`array`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html)
- Python 리스트, 예: `[1, 2, 3]`

그리고 다음을 희소 벡터로 인식합니다:
- MLlib의 [`SparseVector`](api/python/reference/api/pyspark.mllib.linalg.SparseVector.html).
- 단일 컬럼을 가진 SciPy의 [`csc_matrix`](http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.csc_matrix.html#scipy.sparse.csc_matrix)

효율을 위해 리스트보다는 NumPy 배열을 권장하고, 희소 벡터를 만들 때는 [`Vectors`](api/python/reference/api/pyspark.mllib.linalg.Vectors.html)에 구현된 팩토리 메서드를 사용하는 걸 추천해요.

API에 대한 자세한 내용은 [`Vectors` Python 문서](api/python/reference/api/pyspark.mllib.linalg.Vectors.html)를 참고하세요.
import numpy as np
import scipy.sparse as sps
from pyspark.mllib.linalg import Vectors

# Use a NumPy array as a dense vector.
dv1 = np.array([1.0, 0.0, 3.0])
# Use a Python list as a dense vector.
dv2 = [1.0, 0.0, 3.0]
# Create a SparseVector.
sv1 = Vectors.sparse(3, [0, 2], [1.0, 3.0])
# Use a single-column SciPy csc_matrix as a sparse vector.
sv2 = sps.csc_matrix((np.array([1.0, 3.0]), np.array([0, 2]), np.array([0, 2])), shape=(3, 1))

Scala:

로컬 벡터의 기본 클래스는 [`Vector`](api/scala/org/apache/spark/mllib/linalg/Vector.html)이며, 두 가지 구현을 제공해요: [`DenseVector`](api/scala/org/apache/spark/mllib/linalg/DenseVector.html)와 [`SparseVector`](api/scala/org/apache/spark/mllib/linalg/SparseVector.html). 로컬 벡터를 만들 때는 [`Vectors`](api/scala/org/apache/spark/mllib/linalg/Vectors$.html)에 구현된 팩토리 메서드를 사용하는 걸 권장해요.

API에 대한 자세한 내용은 [`Vector` Scala 문서](api/scala/org/apache/spark/mllib/linalg/Vector.html)와 [`Vectors` Scala 문서](api/scala/org/apache/spark/mllib/linalg/Vectors$.html)를 참고하세요.
import org.apache.spark.mllib.linalg.{Vector, Vectors}

// Create a dense vector (1.0, 0.0, 3.0).
val dv: Vector = Vectors.dense(1.0, 0.0, 3.0)
// Create a sparse vector (1.0, 0.0, 3.0) by specifying its indices and values corresponding to nonzero entries.
val sv1: Vector = Vectors.sparse(3, Array(0, 2), Array(1.0, 3.0))
// Create a sparse vector (1.0, 0.0, 3.0) by specifying its nonzero entries.
val sv2: Vector = Vectors.sparse(3, Seq((0, 1.0), (2, 3.0)))
***참고:*** Scala는 기본적으로 `scala.collection.immutable.Vector`를 import 하기 때문에, MLlib의 `Vector`를 사용하려면 `org.apache.spark.mllib.linalg.Vector`를 명시적으로 import 해야 해요.

Java:

로컬 벡터의 기본 클래스는 [`Vector`](api/java/org/apache/spark/mllib/linalg/Vector.html)이며, 두 가지 구현을 제공해요: [`DenseVector`](api/java/org/apache/spark/mllib/linalg/DenseVector.html)와 [`SparseVector`](api/java/org/apache/spark/mllib/linalg/SparseVector.html). 로컬 벡터를 만들 때는 [`Vectors`](api/java/org/apache/spark/mllib/linalg/Vectors.html)에 구현된 팩토리 메서드를 사용하는 걸 권장해요.

API에 대한 자세한 내용은 [`Vector` Java 문서](api/java/org/apache/spark/mllib/linalg/Vector.html)와 [`Vectors` Java 문서](api/java/org/apache/spark/mllib/linalg/Vectors.html)를 참고하세요.
import org.apache.spark.mllib.linalg.Vector;
import org.apache.spark.mllib.linalg.Vectors;

// Create a dense vector (1.0, 0.0, 3.0).
Vector dv = Vectors.dense(1.0, 0.0, 3.0);
// Create a sparse vector (1.0, 0.0, 3.0) by specifying its indices and values corresponding to nonzero entries.
Vector sv = Vectors.sparse(3, new int[] {0, 2}, new double[] {1.0, 3.0});

레이블된 포인트 (Labeled point)

레이블된 포인트는 레이블/응답과 연결된 로컬 벡터(조밀 또는 희소)예요. MLlib에서 레이블된 포인트는 지도 학습 알고리즘에 사용됩니다. 레이블을 저장하는 데 double을 사용하므로, 레이블된 포인트를 회귀와 분류 양쪽 모두에 사용할 수 있어요. 이진 분류의 경우 레이블은 0(음성) 또는 1(양성)이어야 합니다. 다중 클래스 분류의 경우 레이블은 0부터 시작하는 클래스 인덱스여야 해요: 0, 1, 2, ....

Python:

레이블된 포인트는 [`LabeledPoint`](api/python/reference/api/pyspark.mllib.regression.LabeledPoint.html)로 표현됩니다.

API에 대한 자세한 내용은 [`LabeledPoint` Python 문서](api/python/reference/api/pyspark.mllib.regression.LabeledPoint.html)를 참고하세요.
from pyspark.mllib.linalg import SparseVector
from pyspark.mllib.regression import LabeledPoint

# Create a labeled point with a positive label and a dense feature vector.
pos = LabeledPoint(1.0, [1.0, 0.0, 3.0])

# Create a labeled point with a negative label and a sparse feature vector.
neg = LabeledPoint(0.0, SparseVector(3, [0, 2], [1.0, 3.0]))

Scala:

레이블된 포인트는 케이스 클래스 [`LabeledPoint`](api/scala/org/apache/spark/mllib/regression/LabeledPoint.html)로 표현됩니다.

API에 대한 자세한 내용은 [`LabeledPoint` Scala 문서](api/scala/org/apache/spark/mllib/regression/LabeledPoint.html)를 참고하세요.
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.LabeledPoint

// Create a labeled point with a positive label and a dense feature vector.
val pos = LabeledPoint(1.0, Vectors.dense(1.0, 0.0, 3.0))

// Create a labeled point with a negative label and a sparse feature vector.
val neg = LabeledPoint(0.0, Vectors.sparse(3, Array(0, 2), Array(1.0, 3.0)))

Java:

레이블된 포인트는 [`LabeledPoint`](api/java/org/apache/spark/mllib/regression/LabeledPoint.html)로 표현됩니다.

API에 대한 자세한 내용은 [`LabeledPoint` Java 문서](api/java/org/apache/spark/mllib/regression/LabeledPoint.html)를 참고하세요.
import org.apache.spark.mllib.linalg.Vectors;
import org.apache.spark.mllib.regression.LabeledPoint;

// Create a labeled point with a positive label and a dense feature vector.
LabeledPoint pos = new LabeledPoint(1.0, Vectors.dense(1.0, 0.0, 3.0));

// Create a labeled point with a negative label and a sparse feature vector.
LabeledPoint neg = new LabeledPoint(0.0, Vectors.sparse(3, new int[] {0, 2}, new double[] {1.0, 3.0}));

희소 데이터 (Sparse data)

실제로는 희소 훈련 데이터가 아주 흔해요. MLlib은 LIBSVMLIBLINEAR이 기본으로 사용하는 LIBSVM 형식으로 저장된 훈련 예제를 읽을 수 있습니다. 각 줄이 다음 형식의 레이블된 희소 피처 벡터를 나타내는 텍스트 형식이에요:

label index1:value1 index2:value2 ...

여기서 인덱스는 1-기반이고 오름차순이에요. 로드한 후에는 피처 인덱스가 0-기반으로 변환됩니다.

Python:

[`MLUtils.loadLibSVMFile`](api/python/reference/api/pyspark.mllib.util.MLUtils.html)은 LIBSVM 형식으로 저장된 훈련 예제를 읽어요.

API에 대한 자세한 내용은 [`MLUtils` Python 문서](api/python/reference/api/pyspark.mllib.util.MLUtils.html)를 참고하세요.
from pyspark.mllib.util import MLUtils

examples = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")

Scala:

[`MLUtils.loadLibSVMFile`](api/scala/org/apache/spark/mllib/util/MLUtils$.html)은 LIBSVM 형식으로 저장된 훈련 예제를 읽어요.

API에 대한 자세한 내용은 [`MLUtils` Scala 문서](api/scala/org/apache/spark/mllib/util/MLUtils$.html)를 참고하세요.
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.rdd.RDD

val examples: RDD[LabeledPoint] = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")

Java:

[`MLUtils.loadLibSVMFile`](api/java/org/apache/spark/mllib/util/MLUtils.html)은 LIBSVM 형식으로 저장된 훈련 예제를 읽어요.

API에 대한 자세한 내용은 [`MLUtils` Java 문서](api/java/org/apache/spark/mllib/util/MLUtils.html)를 참고하세요.
import org.apache.spark.mllib.regression.LabeledPoint;
import org.apache.spark.mllib.util.MLUtils;
import org.apache.spark.api.java.JavaRDD;

JavaRDD<LabeledPoint> examples = 
  MLUtils.loadLibSVMFile(jsc.sc(), "data/mllib/sample_libsvm_data.txt").toJavaRDD();

로컬 행렬 (Local matrix)

로컬 행렬은 정수 타입의 행/열 인덱스와 double 타입 값을 가지며 단일 머신에 저장됩니다. MLlib은 항목 값을 열-주요(column-major) 순서로 단일 double 배열에 저장하는 조밀 행렬과, 0이 아닌 항목 값을 열-주요 순서의 CSC(Compressed Sparse Column) 형식으로 저장하는 희소 행렬을 지원해요. 예를 들어 다음 조밀 행렬 \[ \begin{pmatrix} 1.0 & 2.0 \\ 3.0 & 4.0 \\ 5.0 & 6.0 \end{pmatrix} \]은 행렬 크기 (3, 2)와 함께 1차원 배열 [1.0, 3.0, 5.0, 2.0, 4.0, 6.0]로 저장됩니다.

Python:

로컬 행렬의 기본 클래스는 [`Matrix`](api/python/reference/api/pyspark.mllib.linalg.Matrix.html)이고, 두 가지 구현을 제공해요: [`DenseMatrix`](api/python/reference/api/pyspark.mllib.linalg.DenseMatrix.html)와 [`SparseMatrix`](api/python/reference/api/pyspark.mllib.linalg.SparseMatrix.html). 로컬 행렬을 만들 때는 [`Matrices`](api/python/reference/api/pyspark.mllib.linalg.Matrices.html)에 구현된 팩토리 메서드를 권장해요. MLlib의 로컬 행렬은 열-주요 순서로 저장된다는 점을 기억하세요.

API에 대한 자세한 내용은 [`Matrix` Python 문서](api/python/reference/api/pyspark.mllib.linalg.Matrix.html)와 [`Matrices` Python 문서](api/python/reference/api/pyspark.mllib.linalg.Matrices.html)를 참고하세요.
from pyspark.mllib.linalg import Matrix, Matrices

# Create a dense matrix ((1.0, 2.0), (3.0, 4.0), (5.0, 6.0))
dm2 = Matrices.dense(3, 2, [1, 3, 5, 2, 4, 6])

# Create a sparse matrix ((9.0, 0.0), (0.0, 8.0), (0.0, 6.0))
sm = Matrices.sparse(3, 2, [0, 1, 3], [0, 2, 1], [9, 6, 8])

Scala:

로컬 행렬의 기본 클래스는 [`Matrix`](api/scala/org/apache/spark/mllib/linalg/Matrix.html)이고, 두 가지 구현을 제공해요: [`DenseMatrix`](api/scala/org/apache/spark/mllib/linalg/DenseMatrix.html)와 [`SparseMatrix`](api/scala/org/apache/spark/mllib/linalg/SparseMatrix.html). 로컬 행렬을 만들 때는 [`Matrices`](api/scala/org/apache/spark/mllib/linalg/Matrices$.html)에 구현된 팩토리 메서드를 권장해요. MLlib의 로컬 행렬은 열-주요 순서로 저장된다는 점을 기억하세요.

API에 대한 자세한 내용은 [`Matrix` Scala 문서](api/scala/org/apache/spark/mllib/linalg/Matrix.html)와 [`Matrices` Scala 문서](api/scala/org/apache/spark/mllib/linalg/Matrices$.html)를 참고하세요.
import org.apache.spark.mllib.linalg.{Matrix, Matrices}

// Create a dense matrix ((1.0, 2.0), (3.0, 4.0), (5.0, 6.0))
val dm: Matrix = Matrices.dense(3, 2, Array(1.0, 3.0, 5.0, 2.0, 4.0, 6.0))

// Create a sparse matrix ((9.0, 0.0), (0.0, 8.0), (0.0, 6.0))
val sm: Matrix = Matrices.sparse(3, 2, Array(0, 1, 3), Array(0, 2, 1), Array(9, 6, 8))

Java:

로컬 행렬의 기본 클래스는 [`Matrix`](api/java/org/apache/spark/mllib/linalg/Matrix.html)이고, 두 가지 구현을 제공해요: [`DenseMatrix`](api/java/org/apache/spark/mllib/linalg/DenseMatrix.html)와 [`SparseMatrix`](api/java/org/apache/spark/mllib/linalg/SparseMatrix.html). 로컬 행렬을 만들 때는 [`Matrices`](api/java/org/apache/spark/mllib/linalg/Matrices.html)에 구현된 팩토리 메서드를 권장해요. MLlib의 로컬 행렬은 열-주요 순서로 저장된다는 점을 기억하세요.

API에 대한 자세한 내용은 [`Matrix` Java 문서](api/java/org/apache/spark/mllib/linalg/Matrix.html)와 [`Matrices` Java 문서](api/java/org/apache/spark/mllib/linalg/Matrices.html)를 참고하세요.
import org.apache.spark.mllib.linalg.Matrix;
import org.apache.spark.mllib.linalg.Matrices;

// Create a dense matrix ((1.0, 2.0), (3.0, 4.0), (5.0, 6.0))
Matrix dm = Matrices.dense(3, 2, new double[] {1.0, 3.0, 5.0, 2.0, 4.0, 6.0});

// Create a sparse matrix ((9.0, 0.0), (0.0, 8.0), (0.0, 6.0))
Matrix sm = Matrices.sparse(3, 2, new int[] {0, 1, 3}, new int[] {0, 2, 1}, new double[] {9, 6, 8});

분산 행렬 (Distributed matrix)

분산 행렬은 long 타입의 행/열 인덱스와 double 타입 값을 가지며, 하나 이상의 RDD에 분산 저장됩니다. 크고 분산된 행렬을 저장할 때 올바른 형식을 고르는 것은 매우 중요해요. 분산 행렬을 다른 형식으로 변환하려면 전역 셔플(global shuffle)이 필요할 수 있는데, 이는 꽤 비쌉니다. 지금까지 네 가지 유형의 분산 행렬이 구현되어 있어요.

기본 타입은 RowMatrix라고 해요. RowMatrix는 의미 있는 행 인덱스가 없는 행 중심의 분산 행렬로, 예를 들어 피처 벡터의 컬렉션입니다. 각 행이 로컬 벡터인 행들의 RDD로 뒷받침됩니다. RowMatrix의 경우 열 수가 너무 크지 않다고 가정해서, 단일 로컬 벡터를 드라이버에 합리적으로 전달할 수 있고 단일 노드로 저장/연산할 수 있다고 봐요.

IndexedRowMatrixRowMatrix와 비슷하지만 행 인덱스가 있어서, 행을 식별하고 조인을 실행하는 데 사용할 수 있어요. CoordinateMatrix좌표 목록(COO) 형식으로 저장된 분산 행렬로, 항목들의 RDD로 뒷받침됩니다. BlockMatrix(Int, Int, Matrix) 튜플인 MatrixBlock의 RDD로 뒷받침되는 분산 행렬이에요.

참고

분산 행렬의 기본 RDD는 결정적(deterministic)이어야 하는데, 행렬 크기를 캐시하기 때문이에요. 일반적으로 비결정적 RDD를 사용하면 오류가 발생할 수 있습니다.

RowMatrix

RowMatrix는 의미 있는 행 인덱스가 없는 행 중심의 분산 행렬로, 각 행이 로컬 벡터인 행들의 RDD로 뒷받침되어요. 각 행이 로컬 벡터로 표현되므로 열 수는 정수 범위로 제한되지만 실제로는 훨씬 작아야 합니다.

Python:

[`RowMatrix`](api/python/reference/api/pyspark.mllib.linalg.distributed.RowMatrix.html)는 벡터들의 `RDD`에서 만들 수 있어요.

API에 대한 자세한 내용은 [`RowMatrix` Python 문서](api/python/reference/api/pyspark.mllib.linalg.distributed.RowMatrix.html)를 참고하세요.
from pyspark.mllib.linalg.distributed import RowMatrix

# Create an RDD of vectors.
rows = sc.parallelize([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])

# Create a RowMatrix from an RDD of vectors.
mat = RowMatrix(rows)

# Get its size.
m = mat.numRows()  # 4
n = mat.numCols()  # 3

# Get the rows as an RDD of vectors again.
rowsRDD = mat.rows

Scala:

[`RowMatrix`](api/scala/org/apache/spark/mllib/linalg/distributed/RowMatrix.html)는 `RDD[Vector]` 인스턴스에서 만들 수 있어요. 그런 다음 열 요약 통계와 분해(decomposition)를 계산할 수 있습니다. [QR 분해](https://en.wikipedia.org/wiki/QR_decomposition)는 A = QR 형태인데, Q는 직교 행렬, R은 상삼각 행렬이에요. [특이값 분해(SVD)](https://en.wikipedia.org/wiki/Singular_value_decomposition)와 [주성분 분석(PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis)은 [차원 축소](mllib-dimensionality-reduction.html)를 참고하세요.

API에 대한 자세한 내용은 [`RowMatrix` Scala 문서](api/scala/org/apache/spark/mllib/linalg/distributed/RowMatrix.html)를 참고하세요.
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.mllib.linalg.distributed.RowMatrix

val rows: RDD[Vector] = ... // an RDD of local vectors
// Create a RowMatrix from an RDD[Vector].
val mat: RowMatrix = new RowMatrix(rows)

// Get its size.
val m = mat.numRows()
val n = mat.numCols()

// QR decomposition 
val qrResult = mat.tallSkinnyQR(true)

Java:

[`RowMatrix`](api/java/org/apache/spark/mllib/linalg/distributed/RowMatrix.html)는 `JavaRDD<Vector>` 인스턴스에서 만들 수 있어요. 그런 다음 열 요약 통계를 계산할 수 있습니다.

API에 대한 자세한 내용은 [`RowMatrix` Java 문서](api/java/org/apache/spark/mllib/linalg/distributed/RowMatrix.html)를 참고하세요.
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.mllib.linalg.Vector;
import org.apache.spark.mllib.linalg.distributed.RowMatrix;

JavaRDD<Vector> rows = ... // a JavaRDD of local vectors
// Create a RowMatrix from a JavaRDD<Vector>.
RowMatrix mat = new RowMatrix(rows.rdd());

// Get its size.
long m = mat.numRows();
long n = mat.numCols();

// QR decomposition 
QRDecomposition<RowMatrix, Matrix> result = mat.tallSkinnyQR(true);

IndexedRowMatrix

IndexedRowMatrixRowMatrix와 비슷하지만 의미 있는 행 인덱스가 있어요. 각 행이 인덱스(long 타입)와 로컬 벡터로 표현되는 인덱스된 행들의 RDD로 뒷받침됩니다.

Python:

[`IndexedRowMatrix`](api/python/reference/api/pyspark.mllib.linalg.distributed.IndexedRowMatrix.html)는 `IndexedRow`들의 `RDD`에서 만들 수 있어요. 여기서 [`IndexedRow`](api/python/reference/api/pyspark.mllib.linalg.distributed.IndexedRow.html)는 `(long, vector)`의 래퍼입니다. `IndexedRowMatrix`는 행 인덱스를 버려서 `RowMatrix`로 변환할 수 있어요.

API에 대한 자세한 내용은 [`IndexedRowMatrix` Python 문서](api/python/reference/api/pyspark.mllib.linalg.distributed.IndexedRowMatrix.html)를 참고하세요.
from pyspark.mllib.linalg.distributed import IndexedRow, IndexedRowMatrix

# Create an RDD of indexed rows.
#   - This can be done explicitly with the IndexedRow class:
indexedRows = sc.parallelize([IndexedRow(0, [1, 2, 3]),
                              IndexedRow(1, [4, 5, 6]),
                              IndexedRow(2, [7, 8, 9]),
                              IndexedRow(3, [10, 11, 12])])
#   - or by using (long, vector) tuples:
indexedRows = sc.parallelize([(0, [1, 2, 3]), (1, [4, 5, 6]),
                              (2, [7, 8, 9]), (3, [10, 11, 12])])

# Create an IndexedRowMatrix from an RDD of IndexedRows.
mat = IndexedRowMatrix(indexedRows)

# Get its size.
m = mat.numRows()  # 4
n = mat.numCols()  # 3

# Get the rows as an RDD of IndexedRows.
rowsRDD = mat.rows

# Convert to a RowMatrix by dropping the row indices.
rowMat = mat.toRowMatrix()

Scala:

[`IndexedRowMatrix`](api/scala/org/apache/spark/mllib/linalg/distributed/IndexedRowMatrix.html)는 `RDD[IndexedRow]` 인스턴스에서 만들 수 있어요. 여기서 [`IndexedRow`](api/scala/org/apache/spark/mllib/linalg/distributed/IndexedRow.html)는 `(Long, Vector)`의 래퍼입니다. `IndexedRowMatrix`는 행 인덱스를 버려서 `RowMatrix`로 변환할 수 있어요.

API에 대한 자세한 내용은 [`IndexedRowMatrix` Scala 문서](api/scala/org/apache/spark/mllib/linalg/distributed/IndexedRowMatrix.html)를 참고하세요.
import org.apache.spark.mllib.linalg.distributed.{IndexedRow, IndexedRowMatrix, RowMatrix}

val rows: RDD[IndexedRow] = ... // an RDD of indexed rows
// Create an IndexedRowMatrix from an RDD[IndexedRow].
val mat: IndexedRowMatrix = new IndexedRowMatrix(rows)

// Get its size.
val m = mat.numRows()
val n = mat.numCols()

// Drop its row indices.
val rowMat: RowMatrix = mat.toRowMatrix()

Java:

[`IndexedRowMatrix`](api/java/org/apache/spark/mllib/linalg/distributed/IndexedRowMatrix.html)는 `JavaRDD<IndexedRow>` 인스턴스에서 만들 수 있어요. 여기서 [`IndexedRow`](api/java/org/apache/spark/mllib/linalg/distributed/IndexedRow.html)는 `(long, Vector)`의 래퍼입니다. `IndexedRowMatrix`는 행 인덱스를 버려서 `RowMatrix`로 변환할 수 있어요.

API에 대한 자세한 내용은 [`IndexedRowMatrix` Java 문서](api/java/org/apache/spark/mllib/linalg/distributed/IndexedRowMatrix.html)를 참고하세요.
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.mllib.linalg.distributed.IndexedRow;
import org.apache.spark.mllib.linalg.distributed.IndexedRowMatrix;
import org.apache.spark.mllib.linalg.distributed.RowMatrix;

JavaRDD<IndexedRow> rows = ... // a JavaRDD of indexed rows
// Create an IndexedRowMatrix from a JavaRDD<IndexedRow>.
IndexedRowMatrix mat = new IndexedRowMatrix(rows.rdd());

// Get its size.
long m = mat.numRows();
long n = mat.numCols();

// Drop its row indices.
RowMatrix rowMat = mat.toRowMatrix();

CoordinateMatrix

CoordinateMatrix는 항목들의 RDD로 뒷받침되는 분산 행렬이에요. 각 항목은 (i: Long, j: Long, value: Double) 튜플인데, i는 행 인덱스, j는 열 인덱스, value는 항목 값입니다. CoordinateMatrix는 행렬의 두 차원 모두 매우 크고 행렬이 매우 희소할 때만 사용해야 해요.

Python:

[`CoordinateMatrix`](api/python/reference/api/pyspark.mllib.linalg.distributed.CoordinateMatrix.html)는 `MatrixEntry` 항목들의 `RDD`에서 만들 수 있어요. 여기서 [`MatrixEntry`](api/python/reference/api/pyspark.mllib.linalg.distributed.MatrixEntry.html)는 `(long, long, float)`의 래퍼입니다. `CoordinateMatrix`는 `toRowMatrix`를 호출해 `RowMatrix`로, 또는 `toIndexedRowMatrix`를 호출해 희소 행을 가진 `IndexedRowMatrix`로 변환할 수 있어요.

API에 대한 자세한 내용은 [`CoordinateMatrix` Python 문서](api/python/reference/api/pyspark.mllib.linalg.distributed.CoordinateMatrix.html)를 참고하세요.
from pyspark.mllib.linalg.distributed import CoordinateMatrix, MatrixEntry

# Create an RDD of coordinate entries.
#   - This can be done explicitly with the MatrixEntry class:
entries = sc.parallelize([MatrixEntry(0, 0, 1.2), MatrixEntry(1, 0, 2.1), MatrixEntry(2, 1, 3.7)])
#   - or using (long, long, float) tuples:
entries = sc.parallelize([(0, 0, 1.2), (1, 0, 2.1), (2, 1, 3.7)])

# Create a CoordinateMatrix from an RDD of MatrixEntries.
mat = CoordinateMatrix(entries)

# Get its size.
m = mat.numRows()  # 3
n = mat.numCols()  # 2

# Get the entries as an RDD of MatrixEntries.
entriesRDD = mat.entries

# Convert to a RowMatrix.
rowMat = mat.toRowMatrix()

# Convert to an IndexedRowMatrix.
indexedRowMat = mat.toIndexedRowMatrix()

# Convert to a BlockMatrix.
blockMat = mat.toBlockMatrix()

Scala:

[`CoordinateMatrix`](api/scala/org/apache/spark/mllib/linalg/distributed/CoordinateMatrix.html)는 `RDD[MatrixEntry]` 인스턴스에서 만들 수 있어요. 여기서 [`MatrixEntry`](api/scala/org/apache/spark/mllib/linalg/distributed/MatrixEntry.html)는 `(Long, Long, Double)`의 래퍼입니다. `CoordinateMatrix`는 `toIndexedRowMatrix`를 호출해 희소 행을 가진 `IndexedRowMatrix`로 변환할 수 있어요. `CoordinateMatrix`의 다른 계산은 현재 지원되지 않습니다.

API에 대한 자세한 내용은 [`CoordinateMatrix` Scala 문서](api/scala/org/apache/spark/mllib/linalg/distributed/CoordinateMatrix.html)를 참고하세요.
import org.apache.spark.mllib.linalg.distributed.{CoordinateMatrix, MatrixEntry}

val entries: RDD[MatrixEntry] = ... // an RDD of matrix entries
// Create a CoordinateMatrix from an RDD[MatrixEntry].
val mat: CoordinateMatrix = new CoordinateMatrix(entries)

// Get its size.
val m = mat.numRows()
val n = mat.numCols()

// Convert it to an IndexRowMatrix whose rows are sparse vectors.
val indexedRowMatrix = mat.toIndexedRowMatrix()

Java:

[`CoordinateMatrix`](api/java/org/apache/spark/mllib/linalg/distributed/CoordinateMatrix.html)는 `JavaRDD<MatrixEntry>` 인스턴스에서 만들 수 있어요. 여기서 [`MatrixEntry`](api/java/org/apache/spark/mllib/linalg/distributed/MatrixEntry.html)는 `(long, long, double)`의 래퍼입니다. `CoordinateMatrix`는 `toIndexedRowMatrix`를 호출해 희소 행을 가진 `IndexedRowMatrix`로 변환할 수 있어요. `CoordinateMatrix`의 다른 계산은 현재 지원되지 않습니다.

API에 대한 자세한 내용은 [`CoordinateMatrix` Java 문서](api/java/org/apache/spark/mllib/linalg/distributed/CoordinateMatrix.html)를 참고하세요.
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.mllib.linalg.distributed.CoordinateMatrix;
import org.apache.spark.mllib.linalg.distributed.IndexedRowMatrix;
import org.apache.spark.mllib.linalg.distributed.MatrixEntry;

JavaRDD<MatrixEntry> entries = ... // a JavaRDD of matrix entries
// Create a CoordinateMatrix from a JavaRDD<MatrixEntry>.
CoordinateMatrix mat = new CoordinateMatrix(entries.rdd());

// Get its size.
long m = mat.numRows();
long n = mat.numCols();

// Convert it to an IndexRowMatrix whose rows are sparse vectors.
IndexedRowMatrix indexedRowMatrix = mat.toIndexedRowMatrix();

BlockMatrix

BlockMatrixMatrixBlock들의 RDD로 뒷받침되는 분산 행렬이에요. MatrixBlock((Int, Int), Matrix) 튜플인데, (Int, Int)는 블록의 인덱스, Matrix는 주어진 인덱스에 있는 크기 rowsPerBlock x colsPerBlock의 부분 행렬입니다. BlockMatrix는 다른 BlockMatrix와의 addmultiply 같은 메서드를 지원해요. BlockMatrix에는 validate 헬퍼 함수도 있어서 BlockMatrix가 제대로 설정되었는지 확인할 수 있습니다.

Python:

[`BlockMatrix`](api/python/reference/api/pyspark.mllib.linalg.distributed.BlockMatrix.html)는 부분 행렬 블록들의 `RDD`에서 만들 수 있어요. 여기서 부분 행렬 블록은 `((blockRowIndex, blockColIndex), sub-matrix)` 튜플입니다.

API에 대한 자세한 내용은 [`BlockMatrix` Python 문서](api/python/reference/api/pyspark.mllib.linalg.distributed.BlockMatrix.html)를 참고하세요.
from pyspark.mllib.linalg import Matrices
from pyspark.mllib.linalg.distributed import BlockMatrix

# Create an RDD of sub-matrix blocks.
blocks = sc.parallelize([((0, 0), Matrices.dense(3, 2, [1, 2, 3, 4, 5, 6])),
                         ((1, 0), Matrices.dense(3, 2, [7, 8, 9, 10, 11, 12]))])

# Create a BlockMatrix from an RDD of sub-matrix blocks.
mat = BlockMatrix(blocks, 3, 2)

# Get its size.
m = mat.numRows()  # 6
n = mat.numCols()  # 2

# Get the blocks as an RDD of sub-matrix blocks.
blocksRDD = mat.blocks

# Convert to a LocalMatrix.
localMat = mat.toLocalMatrix()

# Convert to an IndexedRowMatrix.
indexedRowMat = mat.toIndexedRowMatrix()

# Convert to a CoordinateMatrix.
coordinateMat = mat.toCoordinateMatrix()

Scala:

[`BlockMatrix`](api/scala/org/apache/spark/mllib/linalg/distributed/BlockMatrix.html)는 `toBlockMatrix`를 호출해 `IndexedRowMatrix`나 `CoordinateMatrix`에서 가장 쉽게 만들 수 있어요. `toBlockMatrix`는 기본적으로 1024 x 1024 크기의 블록을 만들어요. 사용자는 `toBlockMatrix(rowsPerBlock, colsPerBlock)`로 값을 제공해 블록 크기를 바꿀 수 있습니다.

API에 대한 자세한 내용은 [`BlockMatrix` Scala 문서](api/scala/org/apache/spark/mllib/linalg/distributed/BlockMatrix.html)를 참고하세요.
import org.apache.spark.mllib.linalg.distributed.{BlockMatrix, CoordinateMatrix, MatrixEntry}

val entries: RDD[MatrixEntry] = ... // an RDD of (i, j, v) matrix entries
// Create a CoordinateMatrix from an RDD[MatrixEntry].
val coordMat: CoordinateMatrix = new CoordinateMatrix(entries)
// Transform the CoordinateMatrix to a BlockMatrix
val matA: BlockMatrix = coordMat.toBlockMatrix().cache()

// Validate whether the BlockMatrix is set up properly. Throws an Exception when it is not valid.
// Nothing happens if it is valid.
matA.validate()

// Calculate A^T A.
val ata = matA.transpose.multiply(matA)

Java:

[`BlockMatrix`](api/java/org/apache/spark/mllib/linalg/distributed/BlockMatrix.html)는 `toBlockMatrix`를 호출해 `IndexedRowMatrix`나 `CoordinateMatrix`에서 가장 쉽게 만들 수 있어요. `toBlockMatrix`는 기본적으로 1024 x 1024 크기의 블록을 만들어요. 사용자는 `toBlockMatrix(rowsPerBlock, colsPerBlock)`로 값을 제공해 블록 크기를 바꿀 수 있습니다.

API에 대한 자세한 내용은 [`BlockMatrix` Java 문서](api/java/org/apache/spark/mllib/linalg/distributed/BlockMatrix.html)를 참고하세요.
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.mllib.linalg.distributed.BlockMatrix;
import org.apache.spark.mllib.linalg.distributed.CoordinateMatrix;
import org.apache.spark.mllib.linalg.distributed.IndexedRowMatrix;

JavaRDD<MatrixEntry> entries = ... // a JavaRDD of (i, j, v) Matrix Entries
// Create a CoordinateMatrix from a JavaRDD<MatrixEntry>.
CoordinateMatrix coordMat = new CoordinateMatrix(entries.rdd());
// Transform the CoordinateMatrix to a BlockMatrix
BlockMatrix matA = coordMat.toBlockMatrix().cache();

// Validate whether the BlockMatrix is set up properly. Throws an Exception when it is not valid.
// Nothing happens if it is valid.
matA.validate();

// Calculate A^T A.
BlockMatrix ata = matA.transpose().multiply(matA);

더 알아보기 (Learn more)