Python3エンジニア認定データ分析試験の学習内容をまとめてみた。
Numpy
数値計算に特化したライブラリ。Python標準のリストに比べて多次元配列のデータを効率よく扱える。
1次元配列
入力
a = np.array([1,2,3])
print(a)
出力
[1 2 3]
入力
type(a)
出力
numpy.ndarray
※ type →オブジェクトの型を返す。変数aはndarray型であることが分かる。ndarrayは多次元配列を扱うデータ構造。
入力
a.shape
出力
(3,)
※ shape → 形状を表す。(行、列)の形で表示される。
2次元配列
b = np.array([[1,2,3],[4,5,6]])
b.shape
出力
(2,3)
変形(reshape)
次元の変換を行える。
入力
c1 = np.array([0,1,2,3,4,5,6])
c2 = c1.reshape((2,3))
print(c2)
出力
[[0 1 2]
[3 4 5]]
要素の数が合わない場合エラーとなる。
入力
c1 = np.array([0,1,2,3,4,5,6])
c2 = c1.reshape((3,4))
print(c2)
出力
ValueError: cannot reshape array of size 7 into shape (3,4)
多次元配列を1次元配列に変換するrevel、flattenを実行
revelは参照、flattenはコピーを返す。
入力
c3 = c2.ravel()
print(c3)
出力
[ 0 1 2 3 4 5]
入力
c4 = c2.flatten()
print(c4)
出力
[ 0 1 2 3 4 5]
データ型(dtype)
データ型を返す。
入力
print(a.dtype)
出力
int64
・明示的な型宣言
入力
d = np.array([1,2],dtype=np.int16)
print(d.dtype)
出力
int16
・型変換
入力
d =d.astype(np.float16)
print(d.dtype)
出力
float16
インデックスとスライス
・インデックス
入力
print(a[0])
出力
1
・スライス
入力
print(a[1:])
出力
2,3
・負のインデックス
配列の末尾から数える
入力
print(a[-1])
出力
3
・2次元配列(インデックス)
入力
print(b[1,0])
出力
4
・2次元配列(スライス)
入力
print(b[:,2])
出力
[3 6]
入力
print(b[1,:])
出力
[4 5 6]
・値が飛んでいる場合
入力
print(b[:,[0,2]])
出力
[[1 3]
[4 6]]
参照とコピー
参照
- 変数aをa1に代入
入力
a1 = a
print(a)
出力
[1 2 3]
- a1の値を変更
入力
a1[1] = 5
print(a1)
出力
[1 5 3]
- aの値を確認
入力
print(a)
出力
[1 5 3]
a1 = a という操作では、aを参照するオブジェクトとしてa1が生成される。よって、a1を変更するとaも変更される。
コピー
- 変数aをa2にコピー
入力
a2 = a.copy()
print(a2)
出力
[1 5 3]
- a2の値を変更
入力
a2[0] = 6
print(a2)
出力
[6 5 3]
- aの値を確認
入力
print(a)
出力
[1 5 3]
a2を変更してもaはそのままの値。
数列を返す(arange)
・引数1つ
入力
print(np.arange(10))
出力
[0 1 2 3 4 5 6 7 8 9]
・引数2つ(1から11の手前までの数列を返す)
入力
print(np.arange(1,11))
出力
[1 2 3 4 5 6 7 8 9 10]
・引数3つ(1から11の手前まで2ずつ増加する数列を返す)
入力
print(np.arange(1,11,2))
出力
[1 3 5 7 9]
乱数
疑似乱数を発生させる。
0〜1間のランダムの要素を持つ行列を作る
入力
rng = np.random.default_rng()
f = rng.random(3,2)
print(f)
出力
[[0.37454012 0.95071431]
[0.73199394 0.59865848]
[0.15601864 0.15599452]]
整数をランダムで出力する
入力
rng = np.random.default_rng()
print(rng.integers(1,10))
出力
7
・第三引数にsizeを指定
入力
rng = np.random.default_rng()
print(rng.integers(1,10,size=(3,3)))
出力
[[4 7 2]
[8 1 5]
[3 9 6]]
小数値をランダムで出力する
入力
rng = np.random.default_rng()
print(rng.uniform(0.0,5.0,size=(2,3)))
出力
[[2.37454012 4.95071431 1.73199394]
[3.59865848 0.15601864 0.75599452]]
・第一引数と第二引数を省略した場合、0.0〜1.0の範囲となる
入力
rng = np.random.default_rng()
print(rng.uniform(size=(4,3)))
出力
[[0.37454012 0.95071431 0.73199394]
[0.59865848 0.15601864 0.15599452]
[0.05808361 0.86617615 0.60111501]
[0.70807258 0.02058449 0.96990985]]
正規分布に従った乱数を出力する
・平均0、分散1の分布で出力(standard_normal)
入力
rng = np.random.default_rng()
print(rng.standard_normal(size=(4,2))
出力
[[ 0.49671415 -0.1382643 ]
[ 0.64768854 1.52302986]
[-0.23415337 -0.23413696]
[ 1.57921282 0.76743473]]
・平均、標準偏差、形状を指定し乱数を出力する
入力
rng = np.random.default_rng()
print(rng.normal(50,10,3))
出力
[48.67323456 52.14789234 45.98765432]
平均50、標準偏差10で3要素を出力。
同じ要素の数列を作る
入力
print(np.zeros(3))
出力
[0. 0. 0.]
・2次元配列
入力
print(np.ones(3,4))
出力
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
単位行列
体格成分が全て1、それ以外の成分が0になる行列を作る。
入力
print(np.eye(3))
出力
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
指定値で埋める
入力
print(np.full(3,3.14))
出力
[3.14 3.14 3.14]
・2次元配列
入力
print(np.full((2,4),np.pi))
出力
[[3.14159265 3.14159265 3.14159265 3.14159265]
[3.14159265 3.14159265 3.14159265 3.14159265]]
※ pi → 円周率を表す。
範囲指定で均等割りデータを作る
・0から1までを5等分する
入力
print(np.linspace(0,1,5))
出力
[0. 0.25 0.5 0.75 1. ]
要素間の差分
入力
l = np.array([2,2,6,1,3])
print(np.diff(l))
出力
[0 4 -5 2]
連結
入力
print(np.concatenate([a,a1]))
出力
[1 5 3 1 5 3]
2次元配列
入力
b1 = np.array([[10],[20]])
print(np.concatenate([b,b1],axis=1))
出力
[[ 1 2 3 10]
[ 4 5 6 20]]
※ axis → 増やす列数を指定
・hstackで同様の結果
入力
b1 = np.array([[10],[20]])
print(np.hstack([b,b1]))
出力
[[ 1 2 3 10]
[ 4 5 6 20]]
・行を増やす
入力
b2 = np.array([30,60,45])
b3 = np.vstack([b,b2])
print(b3)
出力
[[ 1 2 3]
[ 4 5 6]
[30 60 45]]
分割
入力
first, second = np.hsplit(b3, [2])
print(first)
print(second)
出力
[[ 1 2]
[ 4 5]
[30 60]]
[[ 3]
[ 6]
[45]]
・行方向に分割
入力
first1, second1 = np.vsplit(b3, [2])
print(first)
print(second)
出力
[[1 2 3]
[4 5 6]]
[[30 60 45]]
転置
2次元配列の行と列を入れ替えること。
入力
print(b.T)
出力
[[1 4]
[2 5]
[3 6]]
次元追加
入力
print(a[np.newaxis,:])
出力
[[1 2 3]]
・列を追加
入力
print(a[:,np.newaxis])
出力
[[1]
[2]
[3]]
グリッドデータの生成
入力
m = np.arange(0,4)
n = np.arange(4,7)
xx,yy = np.meshgrid(m,n)
print(xx)
print(yy)
出力
[[0 1 2 3]
[0 1 2 3]
[0 1 2 3]]
[[4 4 4 4]
[5 5 5 5]
[6 6 6 6]]
Numpyの各機能
以下、事前に定義しておく。
a = np.arange(3)
b = np.arange(-3,3).reshape((2,3))
c = np.arange(1,7).reshape((2,3))
d = np.arange(6).reshape((3,2))
e = np.linspace(-1,1,10)
print("a:",a)
print("b:",b)
print("c:",c)
print("d:",d)
print("e:",e)
出力
a: [0 1 2]
b: [[-3 -2 -1]
[ 0 1 2]]
c: [[1 2 3]
[4 5 6]]
d: [[0 1]
[2 3]
[4 5]]
e: [-1. -0.77777778 -0.55555556 -0.33333333 -0.11111111 0.11111111
0.33333333 0.55555556 0.77777778 1. ]
ユニバーサルファンクション
・各要素の絶対値を返す
入力
print(np.abs(b))
出力
[[3 2 1]
[0 1 2]]
・各要素の正弦を返す
入力
print(np.sin(e))
出力
[-0.84147098 -0.70169788 -0.52741539 -0.3271947 -0.11088263 0.11088263
0.3271947 0.52741539 0.70169788 0.84147098]
・各要素の余弦を返す
入力
print(np.cos(e))
出力
[0.54030231 0.71247462 0.84960756 0.94511052 0.99383351 0.99383351
0.94511052 0.84960756 0.71247462 0.54030231]
・各要素のlogを返す
入力
print(np.log(a))
出力
[-inf 0. 0.69314718]
※ -inf →マイナス無限大を表す。
・ネイビア数の冪乗を表す
入力
print(np.exp(a))
出力
[1. 2.71828183 7.3890561 ]
ブロードキャスト
入力
print(a+10)
出力
[10 11 12]
・配列同士の和
入力
print(a+b)
出力
[[-3 -1 1]
[ 0 2 4]]
・各要素を自身の要素の平均値から引いた配列
入力
print(c - np.mean(c))
出力
[[-2.5 -1.5 -0.5]
[ 0.5 1.5 2.5]]
・掛け算
入力
print(b*2)
出力
[[-6 -4 -2]
[ 0 2 4]]
配列の掛け算
入力
print(np.dot(b,a))
出力
[-4 5]
・ 掛ける順番を逆にするとエラー
入力
print(np.dot(a,b))
出力
ValueError: shapes (3,) and (2,3) not aligned: 3 (dim 0) != 2 (dim 0)
・ 2次元配列同士の積
入力
print(np.dot(b,d))
出力
[[ -8 -14]
[ 10 13]]
・順序を逆にした場合
入力
print(np.dot(d,b))
出力
[[ 0 1 2]
[ -6 -1 4]
[-12 -3 6]]
判定・真偽値
入力
print(a>1)
出力
[False False True]
・Trueの数をカウント
入力
print(np.count_nonzero(b>0))
出力
2
※ count_nonzero → 0でない要素数を出力。Falseは0として扱われるため、Trueの数である2が出力される。
・ 要素の中にTrueが含まれているかを確認
入力
print(np.any(b>0))
出力
True
・全てがTrueかどうかを確認
入力
print(np.all(b>0))
出力
False
・条件に合致したものだけ出力
入力
print(b[b>0])
出力
[1 2]
・ 配列同士が同じ要素で構成されているかを確認
入力
print(np.allclose(b,c))
出力
False
・誤差を指定し、誤差の範囲内であればTrueを出力
入力
print(np.allclose(b,c,atol=10.0))
出力
True
pandas
データ解析のためのライブラリ。
Numpyを基盤にシリーズとデータフレームというデータ型を提供。
Series
一次元データ。
入力
import pandas as pd
ser = pd.series([10,20,30,40])
print(ser)
出力
0 10
1 20
2 30
3 40
dtype: int64
DataFrame
2次元のデータ。
入力
df = pd.DataFrame([
[10,"a",True],
[20,"b",False],
[30,"c",False],
[40,"d",True]])
print(df)
出力
0 1 2
0 10 a True
1 20 b False
2 30 c False
3 40 d True
・arangeを活用
入力
df = pd.DataFrame(np.arange(100).reshape((25,4)))
print(df.head())
print(df.tail())
出力
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
4 16 17 18 19
0 1 2 3
20 80 81 82 83
21 84 85 86 87
22 88 89 90 91
23 92 93 94 95
24 96 97 98 99
※ head() → 先頭五行を出力
tail() → 末尾五行を出力。
インデックス名、カラム名
行名、列名を指定できる。
入力
df = pd.DataFrame(np.arange(6).reshape((3,2)))
df.index = ["01","02","03"]
df.columns = ["A","B"]
print(df)
出力
A B
01 0 1
02 2 3
03 4 5
データ抽出
入力
df = pd.DataFrame(np.arange(12).reshape((4,3)),
columns = ["A","B","C"],
index = ["1行目","2行目","3行目","4行目"])
print(df["A"])
出力
1行目 0
2行目 3
3行目 6
4行目 9
Name: A, dtype: int64
・ インデクサを使った抽出(loc)
loc(行名、列名)の形で指定する。
入力
print(df.loc[:,"A"])
出力
1行目 0
2行目 3
3行目 6
4行目 9
Name: A, dtype: int64
・ インデクサを使った抽出(iloc)
iloc(行番号、列番号)の形で指定。
入力
print(df.iloc[:,0])
出力
1行目 0
2行目 3
3行目 6
4行目 9
Name: A, dtype: int64
時系列データ
1ヶ月分のデータを作る
入力
dates = pd.date_range(start="2025-04-01",
end="2025-04-30")
print(dates)
出力
DatetimeIndex(['2025-04-01', '2025-04-02', '2025-04-03', '2025-04-04',
'2025-04-05', '2025-04-06', '2025-04-07', '2025-04-08',
'2025-04-09', '2025-04-10', '2025-04-11', '2025-04-12',
'2025-04-13', '2025-04-14', '2025-04-15', '2025-04-16',
'2025-04-17', '2025-04-18', '2025-04-19', '2025-04-20',
'2025-04-21', '2025-04-22', '2025-04-23', '2025-04-24',
'2025-04-25', '2025-04-26', '2025-04-27', '2025-04-28',
'2025-04-29', '2025-04-30'],
dtype='datetime64[ns]', freq='D')
・日付をインデックスにする
入力
rng = np.random.default_rng(123)
df = pd.DataFrame(rng.integers(1,31,size=30),
index=dates,
columns=["乱数値"])
print(df.head())
出力
乱数値
2025-04-01 6
2025-04-02 3
2025-04-03 7
2025-04-04 4
2025-04-05 6
Matplotlib
2次元のグラフを描画するためのライブラリ。
pyplotインタフェース
入力
import matplotlib.pyplot as plt
x = [1,2,3]
y = [2,4,9]
plt.plot(x,y)
plt.title('pyplot interface')
plt.show()
出力
オブジェクト指向インタフェース
描画オブジェクトにサブプロットを追加し、サブプロットに対しグラフを描画する。
入力
x = [1,2,3]
y = [2,4,9]
fig,ax = plt.subplots()
ax.plot(x,y)
ax.set_title('object-oriented interface')
plt.show()
出力
・2つのサブプロットを配置
入力
flg,axes = plt.subplots(2)
plt.show()
出力
軸ラベル
グラフの軸にラベルを指定できる。
入力
flg,ax = plt.subplots()
ax.set_xlabel('x label')
ax.set_ylabel('y label')
plt.show()
出力
反例
入力
flg,ax = plt.subplots()
ax.plot([1,2,3],[2,4,9],label='legend label')
ax.legend(loc='best')
plt.show()
※ loc='best' → データとの重なりが最小な位置に反例を出力。
ファイル出力
入力
flg,ax = plt.subplots()
ax.set_title('subplot title')
flg.savefig('sample-figure.png')
棒グラフ
入力
flg,ax = plt.subplots()
x = [1,2,3]
y = [10,2,3]
ax.bar(x,y)
plt.show()
・横向きの棒グラフ
入力
flg,ax = plt.subplots()
x = [1,2,3]
y = [10,2,3]
ax.barh(x,y)
plt.show()
散布図
入力
flg,ax = plt.subplots()
rng = np.random.default_rng(123)
x = rng.random(50)
y = rng.random(50)
ax.scatter(x,y)
plt.show()
出力
ヒストグラム
入力
rng = np.random.default_rng(123)
mu = 100
sigma = 15
x = rng.normal(mu,sigma,1000)
flg,ax = plt.subplots()
n,bins,patches = ax.hist(x)
plt.show()
・横向きのヒストグラム
入力
flg,ax = plt.subplots()
ax.hist(x,orientation='horizontal')
plt.show()
出力
箱ひげ図
入力
rng = np.random.default_rng(123)
x0 = rng.normal(0,10,500)
x1 = rng.normal(0,15,500)
x2 = rng.normal(0,20,500)
flg,ax = plt.subplots()
labels = ['x0','x1','x2']
ax.boxplot((x0,x1,x2),labels=labels)
plt.show()
・横向きの箱ひげ図
入力
flg,ax = plt.subplots()
labels = ['x0','x1','x2']
ax.boxplot((x0,x1,x2),labels=labels,vert=False)
plt.show()
出力
円グラフ
入力
labels = ['spam','ham','egg']
x = [10,3,1]
flg,ax = plt.subplots()
ax.pie(x,labels=labels)
plt.show()
・12時の位置から時計回りに出力
入力
flg,ax = plt.subplots()
ax.pie(x,labels=labels,startangle=90,counterclock=False)
plt.show()
複数のグラフを組み合わせる
入力
flg,ax = plt.subplots()
x1 = [1,2,3]
y1 = [5,2,3]
x2 = [1,2,3,4]
y2 = [8,5,4,6]
ax.bar(x1,y1,label='y1')
ax.plot(x2,y2,label='y2')
ax.legend()
plt.show()
テキスト描画
入力
flg,ax = plt.subplots()
ax.text(0.2,0.4,'Text',size=20)
plt.show()
pandasのオブジェクトからグラフ描画
入力
matplotlib.style.use('ggplot')
df = pd.DataFrame({'A':[1,2,3],'B':[3,1,2]})
df.plot()
plt.show()
出力
scikt-learn
データマイニングやデータ解析用のライブラリ。
欠損値の補完
入力
from sklearn.impute import SimpleImputer
df = pd.DataFrame(
{'A':[1,np.nan,3,4,5],
'B':[6,7,8,np.nan,10],
'C':[11,12,13,14,15]
}
)
imp = SimpleImputer(strategy='mean')
imp.fit(df)
print(imp.transform(df))
出力
[[ 1. 6. 11. ]
[ 3.25 7. 12. ]
[ 3. 8. 13. ]
[ 4. 7.75 14. ]
[ 5. 10. 15. ]]
カテゴリ変数のエンコーディング
入力
from sklearn.preprocessing import LabelEncoder
df = pd.DataFrame(
{'A':[1,2,3,4,5],
'B':['a','b','a','b','c']
}
)
le = LabelEncoder()
le.fit(df.loc[:,'B'])
print(le.transform(df.loc[:,'B']))
出力
[0 1 0 1 2]
・One-hotエンコーディング
カテゴリ変数に対して行う符号化処理。
入力
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
from sklearn.compose import ColumnTransformer
わ
df_ohe = df.copy()
le = LabelEncoder()
df_ohe.loc[:,'B'] = le.fit_transform(df_ohe.loc[:,'B'])
ohe = ColumnTransformer([("OneHotEncoder",
OneHotEncoder(),[1])],
remainder='passthrough')
df_ohe = ohe.fit_transform(df_ohe)
print(df_ohe)
出力
[[1. 0. 0. 1.]
[0. 1. 0. 2.]
[1. 0. 0. 3.]
[0. 1. 0. 4.]
[0. 0. 1. 5.]]
特徴量の正規化
特徴量の大きさを揃える。
・分散正規化
特徴量の平均が0、標準偏差が1となるように特徴量を変換する処理。
入力
from sklearn.preprocessing import StandardScaler
df = pd.DataFrame(
{
'A': [1,2,3,4,5],
'B': [100,200,400,500,800]
}
)
stdsc = StandardScaler()
stdsc.fit(df)
print(stdsc.transform(df))
出力
[[-1.41421356 -1.22474487]
[-0.70710678 -0.81649658]
[ 0. 0. ]
[ 0.70710678 0.40824829]
[ 1.41421356 1.63299316]]
・最小最大正規化
特徴量の最小値が0、最大値が1を取るように正規化する。
入力
from sklearn.preprocessing import MinMaxSacler
df = pd.DataFrame(
{
'A': [1,2,3,4,5],
'B': [100,200,400,500,800]
}
)
mmsc = MinMaxSacler()
mmsc.fit(df)
print(mmsc.transform(df))
出力
[[0. 0. ]
[0.25 0.14285714]
[0.5 0.42857143]
[0.75 0.57142857]
[1. 1. ]]
分類
データのクラスを予測して分けるタスク。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
iris = load_iris()
X,Y = iris.data,iris.target
X_train,X_test,y_train,y_test = train_test_split(
X,y,test_size=0.3,random_state=123)
サポートベクタマシン
線形分離できないデータを高次元の空間に写して線形分離することで分類を行うアルゴリズム。
入力
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC
# 2番目のコードで定義されたプロット関数
def plot_boundary_margin_sv(X0, y0, X1, y1, kernel, C, xmin=-1, xmax=1, ymin=-1, ymax=1):
# SVMモデルの作成と学習
svc = SVC(kernel=kernel, C=C)
svc.fit(np.vstack((X0, X1)), np.hstack((y0, y1)))
# 散布図のプロット
fig, ax = plt.subplots()
ax.scatter(X0[:, 0], X0[:, 1], marker='o', label='class 0')
ax.scatter(X1[:, 0], X1[:, 1], marker='x', label='class 1')
# 決定境界とマージンのプロット
xx, yy = np.meshgrid(np.linspace(xmin, xmax, 100),
np.linspace(ymin, ymax, 100))
xy = np.vstack([xx.ravel(), yy.ravel()]).T
p = svc.decision_function(xy).reshape((100, 100))
ax.contour(xx, yy, p, colors='k', levels=[-1, 0, 1],
alpha=0.5, linestyles=['--', '-', '--'])
# サポートベクターのプロット
ax.scatter(svc.support_vectors_[:, 0],
svc.support_vectors_[:, 1],
s=250, facecolors='none',
edgecolors='black')
# ラベルと凡例の設定
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend(loc='best')
plt.show()
# 1番目のコードで生成されたデータ
rng = np.random.default_rng(123)
# クラス0のデータ生成
X0 = rng.uniform(size=(100, 2))
y0 = np.repeat(0, 100)
# クラス1のデータ生成
X1 = rng.uniform(-1.0, 0.0, size=(100, 2))
y1 = np.repeat(1, 100)
# プロット関数の呼び出し(カーネルは'linear'、C=1として実行)
plot_boundary_margin_sv(X0, y0, X1, y1, kernel='linear', C=1)
出力
決定木
データを分割するルールを次々と作成していく事による分類を実行。
「データを分割することによってどれだけ得をするか」という情報利得と、「どれだけクラスが混在しているか」という不純度について考える。不純度が下がることにより情報利得が増す。
情報利得は、親ノードの不純度から子ノードの不純度の合計を引くことで求められる。
入力
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X,y = iris.data,iris.target
X_train,X_test,y_train,y_test = train_test_split(
X,y,test_size=0.3,random_state=123)
tree = DecisionTreeClassifier(max_depth=3,
random_state=123)
tree.fit(X_train,y_train)
出力
ランダムフォレスト
データのサンプルと特徴量をランダムに選択して決定木を構築する処理を複数回繰り返し、各木の推定結果の多数決や平均値により分類・回帰を行う手法。
入力
from sklearn.ensemble import RandomForestClassifier
forest = RandomForestClassifier(n_estimators=100,
random_state=123)
forest.fit(X_train,y_train)
y_pred = forest.predict(X_test)
print(y_pred)
出力
[1 2 2 1 0 1 1 0 0 1 2 0 1 2 2 2 0 0 1 0 0 1 0 2 0 0 0 2 2 0 2 1 0 0 1 1 2
0 0 1 1 0 2 2 2]
回帰
ある値を別の単一又は複数の値で説明するタスク。
入力
from sklearn.linear_model import LinearRegression
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
# データの取得
housing = fetch_california_housing()
X, y = housing.data, housing.target
# データを訓練セットとテストセットに分割
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=123)
# 線形回帰モデルの作成
lr = LinearRegression()
# モデルの学習
lr.fit(X_train, y_train)
次元削減
データが持っている情報をなるべく損ねることなく次元を削減してデータを圧縮するタスク。
主成分分析
高次元のデータに対して分散が大きくなる方向を探して元の次元と同じかそれよりも低い次元にデータを変換する手法。
入力
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
rng = np.random.default_rng(123)
X = rng.uniform(size=50)
Y = 2*X + 0.5*rng.uniform(size=50)
pca = PCA(n_components=2)
X_pca = pca.fit_transform(np.hstack((X.reshape(-1,1),
Y.reshape(-1,1))))
fig, ax = plt.subplots()
ax.scatter(X_pca[:,0],X_pca[:,1])
ax.set_xlabel('PC1')
ax.set_ylabel('PC2')
ax.set_xlim(-1.1,1.1)
ax.set_ylim(-1.1,1.1)
plt.show()
モデルの評価
カテゴリの分類精度
・適合率・・正例と予測したもののうち正例であった割合。
・再現率・・正例であったもののうち正例と予測したものの割合。
・F値・・適合率と再現率の調和平均。
・正解率・・予測と実績が一致したデータの割合。
入力
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
iris = load_iris()
X,y = iris.data[:100,:],iris.target[:100]
X_train,X_test,y_train,y_test = train_test_split(
X,y,test_size=0.3,random_state=123)
svc = SVC()
svc.fit(X_train,y_train)
y_pred = svc.predict(X_test)
print(classification_report(y_test,y_pred))
出力
・交差検証
入力
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
svc = SVC()
print(cross_val_score(svc,X,y,cv=10,scoring='precision'))
出力
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
ROC曲線
縦軸に真陽性率、横軸に偽陽性率をプロットして描かれる。
入力
import numpy as np
import matplotlib.pyplot as plt
# 偽陽性率と真陽性率を計算
fpr = np.array([0, 0, 0, 1, 1, 2, 3, 3, 3, 3, 4, 5, 5, 6,
7, 8, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14])/14
tpr = np.array([0, 1, 2, 2, 3, 3, 3, 4, 5, 6, 6, 6, 7, 7,
7, 7, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11])/11
# ROC曲線をプロット
import numpy as np
from sklearn.metrics import roc_curve
# 各データが正解したかどうかを表すダブル
labels = np.array([1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1,
0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0])
# 各データの予測正解確率
probs = np.array([0.98, 0.95, 0.9, 0.87, 0.85,
0.8, 0.75, 0.71, 0.63, 0.55,
0.51, 0.47, 0.43, 0.38, 0.35,
0.31, 0.28, 0.24, 0.22, 0.19,
0.15, 0.12, 0.08, 0.04, 0.01])
# 偽陽性率、真陽性率、しきい値を算出
fpr, tpr, threshold = roc_curve(labels, probs)
fig, ax = plt.subplots()
ax.step(fpr, tpr)
ax.set_xlabel('false positive rate')
ax.set_ylabel('true positive rate')
plt.show()
ハイパーパラメータの最適化
グリッドサーチ
ハイパーパラメータを最適化する代表的な手法の一つ。ハイパーパラメータの候補を指定し、それぞれのハイパーパラメータで学習を行いテストデータセットに対する予測が最も良い値を選択する方法。
入力
from sklearn.datasets import load_iris
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.tree import DecisionTreeClassifier
# Irisデータセットをロード
iris = load_iris()
X, y = iris.data, iris.target
# データを訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=123)
# 決定木をインスタンス化
clf = DecisionTreeClassifier(random_state=123)
param_grid = {'max_depth': [3, 4, 5]}
# 10分割の交差検証を実行
cv = GridSearchCV(clf, param_grid=param_grid, cv=10)
cv.fit(X_train, y_train)
# 推定された最適なモデルを用いて予測
y_pred = cv.predict(X_test)
y_pred
出力
array([1, 2, 2, 1, 0, 1, 1, 0, 0, 1, 2, 0, 1, 2, 2, 2, 0, 0, 1, 0, 0, 1,
0, 2, 0, 0, 0, 2, 2, 0, 2, 1, 0, 0, 1, 1, 2, 0, 0, 1, 1, 0, 2, 2,
2])
クラスタリング
ある基準を設定してデータ間の類似性を計算し、データをクラスタにまとめるタスク。
k-means
データをK個のクラスタに分ける。
入力
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
# Irisデータセットをロード
iris = load_iris()
data = iris.data
# 1, 3列目を抽出(がく片の幅と花弁の幅)
X = data[:100, [1, 3]] # [1, 3]:がく片の幅(Sepal Width)、花弁の幅(Petal Width)
# データを3とするKMeansのインスタンスを生成
km = KMeans(n_clusters=3, init='k-means++', n_init=10, random_state=123)
# KMeansを実行
y_km = km.fit_predict(X)
# 散布図を描写
fig, ax = plt.subplots()
# 散布図(クラスター1)
ax.scatter(X[y_km == 0, 0], X[y_km == 0, 1], s=50,
edgecolor='black', marker='s', label='cluster 1')
# クラスター中心(クラスター1)
ax.plot(np.mean(X[y_km == 0, 0]),
np.mean(X[y_km == 0, 1]),
marker='x', markersize=10, color='red')
# 散布図(クラスター2)
ax.scatter(X[y_km == 1, 0], X[y_km == 1, 1], s=50,
edgecolor='black', marker='o', label='cluster 2')
# クラスター中心(クラスター2)
ax.plot(np.mean(X[y_km == 1, 0]),
np.mean(X[y_km == 1, 1]),
marker='x', markersize=10, color='red')
# 散布図(クラスター3)
ax.scatter(X[y_km == 2, 0], X[y_km == 2, 1], s=50,
edgecolor='black', marker='v', label='cluster 3')
# クラスター中心(クラスター3)
ax.plot(np.mean(X[y_km == 2, 0]),
np.mean(X[y_km == 2, 1]),
marker='x', markersize=10, color='red')
# ラベル設定
ax.set_xlabel('Sepal width')
ax.set_ylabel('Petal width')
# 凡例
ax.legend()
# 表示
plt.show()
出力
凝集型階層的クラスタリング
まず似ているデータをまとめて小さなクラスタを作り、次にそのクラスタと似ているデータをさらにまとめ、最終的にデータが一つのクラスタにまとめられるまで処理を繰り返す方法。
入力
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram
# Irisデータセットをロード
iris = load_iris()
data = iris.data
# 1, 3列目を抽出(がく片の幅と花弁の幅)
X = data[:100, [1, 3]] # [1, 3]:がく片の幅(Sepal Width)、花弁の幅(Petal Width)
# 凝集型クラスタリングのインスタンスを生成(affinityをmetricに変更)
ac = AgglomerativeClustering(n_clusters=3, metric='euclidean', linkage='complete')
# データを更新し、含まれるクラスター番号を取得
labels = ac.fit_predict(X)
# クラスタ間の関係を抽出
children = ac.children_
# クラスタ間の距離を抽出
distance = np.arange(children.shape[0])
# 各データの観測番号
no_of_observations = np.arange(2, children.shape[0]+2)
# マージマス、クラスター間の距離、観測番号を利力向に結合
linkage_matrix = np.hstack((children,
distance.reshape(-1, 1),
no_of_observations.reshape(-1, 1))).astype(float)
# 樹形図をプロット
fig, ax = plt.subplots(figsize=(15, 3), dpi=300)
dendrogram(linkage_matrix, labels=np.arange(100),
leaf_font_size=8, color_threshold=np.inf)
plt.show()
以上。Xも見てね