2023.02.16
Time Series 機械学習のためのPython必須ライブラリ、Numpy 1編
機械学習のためのPython必須ライブラリ、Numpy 1編
機械学習アルゴリズムを勉強する前に、時系列データを扱うためにPython言語のライブラリの使い方に慣れておく必要があります。今回の章では ライブラリを重点的に見て、いくつかの実習例を取り上げる。NumpyとPandasは、大規模なデータを弾力的に処理するための多くの高性能ツールを提供しています。NumpyとPandasが何であるかを見て、その重要な機能について学びましょう。
練習のための環境としては、大きくJ upyter notebookを直接構築してローカルで使用する方法とGoogle Colabを使用する方法がある。迅速な練習環境を構築するためにColabを活用することをお勧めします。
* Numpyとは?
Numerical Pythonの略で、線形代数ベースの算術計算を容易にするライブラリです。Numpyを必須に使用する理由は、大規模な多次元配列、数学的、論理的、形状操作、整列、選択、I/O、離散フーリエに対する迅速な作業変換、基本線形代数、基礎統計演算、ランダムシミュレーションなどのさまざまな作業を支援しているからだ。
2-1. ベクトル、行列、テンソル(Vector、Matrix and Tensor)
機械学習をすれば扱われる最も基本的な単位はベクトル、行列、テンソルである。 次元のない値をスカラー(0次元)、スカラー値で構成された1つの配列をベクトル(1次元)、1次元であるベクトルで構成された1つの2次元配列を行列(Matrix)という。 そして、そのような行列が合わさって一つの行列になると、私たちはテンソルと呼ばれます。
実際、私たちは3次元に住んでいるので、4次元以上からは頭で想像することが難しくなる。 そのため、3次元のテンソルを介して上下に拡張していきながら想像してみよう。 3次元を横に拡張すれば4次元、4次元を上に拡張すれば5次元、6次元は後ろに拡張した姿だ。 しかし、機械学習分野限定で3次元以上のテンソルからは、単に多次元行列または配列とみなすことができる。 主に3次元以上をテンソルというが、1次元ベクトル、2次元の行列の場合もテンソルと表現することもある。 そしてテンソルは軸の個数(次元数)と形状、データ型を持つことになるが、軸の個数(純粋次元数)だけ表現すればRank、各軸による次元数はShapeで表現する。
複数のテンソルごとに使用される方法が異なります。 そして、データ分析用途としては主に3Dテンソルまでのみ使用することになる。 それでは、なぜ3Dテンソルまでしか使用しないのかを見てみましょう。
2Dテンソルの基本特性は、2つの軸(x、y)が存在することです。 そして一般的な数値や統計データセットがほとんど行列になった構造になっているため、2Dテンソルを使っている。
3Dテンソルの場合、2Dテンソルを後ろに積み重ねたまるでキューブのような形で3つの軸が存在します。 当該テンソルの使用用途は、主に白黒画像や、時系列データなどのデータ(株価データセット、経時的な疾病発症など)が存在する。 この時系列で使用するためには、データが連続したシーケンスデータであるか、時間軸を含むデータでなければならないため、特性はFeatures、Timesteps、Samplesの構造を使用する。
2-2. Python、Numpyスピード比較
Numpyライブラリは、既存のPython組み込み関数よりも高速です。 最終的にPythonは動作速度が速い言語ではありません。 C言語より最大200倍、Javaより最大20倍ほど遅いという。 Numpyはこれを補完して高性能パフォーマンスを出すことができるようにするライブラリだ。
import numpy as np
array = np.random.rand(100000)
%timeit sum(array)
%timeit np.sum(array)
그림 2-2-1 Python, Numpy 단순 속도 비교
単純時間だけ比較をしてみても速度差が数百倍出ることがわかる。 Pythonがなぜ遅いのかを見ると、同じデータを表現しても、基本Pythonに比べてNumpyが比較的高速な演算をサポートし、メモリを効率的に使うからだ。 C言語は変数に値を割り当てるときにデータ型を明示してくれ、変数にアクセスするときタイプを知るのですぐにアクセスが可能だが、Pythonはユーザーがデータ型を指定してくれなくても分かって割り当てをするようになる構造だ。 これは、変数にアクセスするたびにどの値が型であるかを毎回チェックする必要があるため、Pythonが遅くなるはずです。 結論として、Numpyは内部的にPythonで遅くなる動作をCで実装することで最適化したため、数十から数百倍の性能向上を示すことができる。 そのため、同じ動作をすることであれば、Python基本で提供する関数よりNumpyを最大限活用するようにしよう。
2-3. Ndarrayを作成する
Numpyのデータ型は、Ndarrayで配列操作を高速化するために開発されました。 PythonリストとNdarrayは柔軟性と効率性の違いがあります。 Pythonリストの場合、異なるデータ型を入れることができ、柔軟性が高い反面、各要素に関する情報をすべて盛り込む必要があるため、占めるメモリのサイズ、繰り返し文の使用が必須である。 このため効率が落ちるしかない。 Ndarrayの場合、同じデータ型同士だけ演算が可能なため柔軟性は落ちるが、すべての要素情報を一度に保存してCで実装されたアルゴリズムを使用するため、速度が非常に速い。 Numpyの場合、Pythonが提供するリストよりも速く、配列を簡単にするための関数を提供しています。
22 / 5,000
翻訳結果
翻訳の結果
Numpyはリストを活用して配列を作成できます。 他に、Numpy.array() 関数の引数としてタプル、Ndarray、mat などの array-like オブジェクトを渡して配列を作成することもできます。 Numpy.array()で作成されたNdarrayオブジェクトはarrayで表されます。 Ndarrayは同じデータ型だけで構成されるので、arr2、arr3のように一つでも別のデータ型が入ってくると、その中で一番大きなデータ型と定義される。
arr1 = np.array([1,2,3,4,5])
arr2 = np.array([1.1,2,3,4,5])
arr3 = np.array([1,2,3,4,5], dtype = float)
print(arr1, arr1.dtype)
print(arr2, arr2.dtype)
print(arr3, arr3.dtype)
図 2-3-1-1. ListによるNumpy配列の作成と型の確認
2-3-2.Ndarrayデータ型、次元サイズの確認
Numpyは同じデータ型同士だけ演算が可能なため、該当配列のデータ型を確認する必要がある。 dtypeは配列内のデータ型が何であるかを知ることができます。
data = np.random.randn(2,3)
print(data)
print(data.dtype)
print(data.shape)
Out [8]:
図 2-3-2-1. Numpy配列生成後のデータ型と型の確認
追加の配列を作成するときは、ndminをオプションで最小次元を指定できます。 そして、次元の追加が必要な時があり、これは行ベクトルを作って計算をするときに軸を合わせるためだ。
arr = np.array([1,2,3])
arr2 = np.array([1,2,3], ndmin = 2)
arr3 = np.array([1,2,3], ndmin = 2)
print(arr)
print(arr.shape)
print(arr2)
print(arr2.shape)
print(arr3.T)
[1 2 3]
(3,)
[[1 2 3]]
(1, 3)
[[1]
[2]
[3]]
図 2-3-2-2. 型、次元の追加、転置行列
配列を作成するときに注意することがあります。 Np.arrayの場合、関数引数としてスカラー型の値を渡すことができます。 そうなると、ndarrayは0次元になり、形状は()、サイズは1になる。 リストに伝える場合は1次元となり、形状は(1,)、サイズは1となる。 つまり、単純にスカラーを引数として渡すことと、リストに引数を渡すことは確実に区別しなければならない。
arr4 = np.array(10)
arr5 = np.array([10])
print(arr4)
print(arr4.shape)
print(arr5)
print(arr5.shape)
Out [14]:
10
()
[10]
(1,)
図 2-3-2-3. 配列を作成する際の注意点
2-3-3. 特定の数で埋められた配列を作成する
指定されたShapeとデータ型で特定の値で埋められた配列を作成できます。
- np.zeros(Shape)
In [15]:
arr_zeros = np.zeros((10,2), dtype = int)
print(arr_zeros)
図 2-3-3-1. ゼロで埋められたサイズ(10、2)のベクトルを生成する
- np.ones(Shape)
In [17]:
arr_ones = np.ones((10,2), dtype = int)
print(arr_ones)
Out [19]:
図 2-3-3-2. 1で埋められたサイズ(10、2)のベクトルを生成する
- np.full(Shape, x)
arr_full = np.full((10,2), 10)
print(arr_full)
Out [22]:
図 2-3-3-3. 10で埋められたサイズが(10,2)ベクトルを生成する
2-3-4. 範囲を指定して配列を作成する
for文の巡回状況などで、Python Range関数のように特定の数列を作成したい場合によく使われます。 PythonのRange、Numpy arange関数と使用方法は同じです。 この関数にも違いがありますが、最初にrangeの場合は整数単位のみをサポートしますが、arangeの場合は実数単位も表現可能です。
print(np.arange(1, 5, 0.5))
Out [24]:
print(range(1, 5, 0.5))
Out [26]:
그림 2-3-4-1. arange와 range의 차이
- np.arange(start, stop, step)
range関数と同じように動作しながらNdarrayを返します。 start から stop まで、step だけスキップされた値からなる配列を返します。
arr_arange = (np.arange(0, 10, 2))
arr_arange
- np.linspace(start, stop, num)
arangeとは異なり、startからstopまでnumだけの間隔を持つ要素の配列を返します。
arr_linspace = np.linspace(0, 10, 5)
arr_linspace
図 2-3-4-3. linsapceを使用した配列の作成
以下はNumpy関数で、他にも多くの関数が存在しています。
array(list or tuple or like_array) | 배열 생성 |
asarray(arr) | 배열안에 데이터가 전부 같은 형태인지 확인 |
copy(arr) | 새로운 주소를 할당하여 복사하려는 배열을 복사 |
arange(start, stop, step) | 주어진 값 내에서 step의 크기만큼 일정하게 떨어져 있는 숫자들을 array 형태로 반환 |
linspace(start, stop, num, endpoint, dtype) | 균등한 견격을 둔 시퀀스를 생성한다. |
meshgrid(*xi, copy =True, sparse = False, indexing= ‘xy’) | 1차원 좌표 배열에서 N차원 직사각형 격자를 만들어 준다. |
mgrid[start:end, start:end] | 브로드 캐스팅을 위한 차원을 늘린 배열 생성 |
ogrid[start:end, start:end] | 브로드 캐스팅을 위한 1Xn, nX1 두개의 행렬 생성 |
diag(v, k]) | 대각 원소 추출하는데 k를 통해 원하는 대각선 |
diagflat(v, k]) | 평평하게 되어 입력의 k 번째 대각선으로 설정 |
tri(m,n, k) | mXn 1인 행렬 생성 뒤 크기 k 만큼 삼각형 0행렬로 변경 뒤 생성 |
vander(x[, N, increasing]) | 방데르몽드 행렬 생성 |
mat(x) | X를 행렬로 변환 |
empty(shape, dtype, order) | 초기화 되지 않은 값으로 배열 생성 |
eye(M, k, dtype) | 2차원 행렬생성 및 대각에 k값인 행렬 생성 |
ones(shape[, dtype, order, like]) | 1로 채워진 행렬 생성 |
zeros(shape[, dtype, order, like]) | 0으로 채워진 행렬 생성 |
full(shape, fill_value[, dtype, order, like]) | 지정된 값으로 행렬 생성 |
Numpy 2編では、索引付け、スライシング、前置行列、算術演算について調べてみよう。