【解説】正規化(z-score, Min-Max normalization)を実装 | データサイエンス100本ノック【問59〜60 回答】

【解説】正規化(z-score, Min-Max normalization)を実装 | データサイエンス100本ノック【問59〜60 回答】

当ページのリンクには広告が含まれています。




目次

この記事の対象者



・ データサイエンティストを目指している人

・ 正規化とはなにかをコードを書きながら理解したい人



以降はデータサイエンス100本ノックの問題を題材にしながら学んでいきます。


データサイエンス100本ノックの始め方は、以下の記事を参考にしていただければと思います。


>>データサイエンス100本ノックの始め方を確認する


第59問目: 標準化

P-059: レシート明細データフレーム(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、合計した売上金額を平均0、標準偏差1に標準化して顧客ID、売上金額合計とともに表示せよ。標準化に使用する標準偏差は、不偏標準偏差と標本標準偏差のどちらでも良いものとする。ただし、顧客IDが”Z”から始まるのものは非会員を表すため、除外して計算すること。結果は10件表示させれば良い。


まず「標準偏差」とは何かを解説します。

標準偏差とは、偏差の2乗の合計値の平均に平方根を取った値です。

???と思った方のために分かりやすい例で解説します。

A B C D 合計
長さ 5 12 11 17 45
偏差(長さ-長さの平均)
長さの平均=11.25
-6.25 0.75 -0.25 5.75 0
偏差の2乗 39.0625 0.5625 0.0625 33.0625 72.75


このようなデータフレームがあった場合、A、B、C、Dの長さの標準偏差は72.75を4で割った値(18.1875)の平方根をとった、4.26となります。

この値が何を表しているかというと、「AからDまでの値がどれだけバラバラなのか」を定量的に示しているのです。

このとき、平均値が0、標準偏差が1になるようにデータを変換することを、標準化(z-score normalization)と呼びます。

数式で書くと以下となります。(µは平均、σは標準偏差です。)

なんのために標準化をするのかというと、異なる種類のデータを1つの尺度にまとめるためです。

これを正規化といいます。

ここで扱うz-score normalizationというのは正規化の手法の1つといえます。

Pythonで標準化を行うにはsklearn.preprocessing.StandardScalerクラスを使用します。

早速本問を解きながら使い方を学んでいきましょう。

まずはdf_receiptの構造を確認します。

1
df_receipt.head(5)
出力
1
2
3
4
5
6
sales_ymd	sales_epoch	store_cd	receipt_no	receipt_sub_no	customer_id	product_cd	quantity	amount
0 20181103 1541203200 S14006 112 1 CS006214000001 P070305012 1 158
1 20181118 1542499200 S13008 1132 2 CS008415000097 P070701017 1 81
2 20170712 1499817600 S14028 1102 1 CS028414000014 P060101005 1 170
3 20190205 1549324800 S14042 1132 1 ZZ000000000000 P050301001 1 25
4 20180821 1534809600 S14025 1102 2 CS025415000050 P060102007 1 90

問題文より、df_receiptのcustomer_idで”Z”から始まるものをqueryメソッドを用いて除外し、groupbyメソッドを用いてcustomer_idごとの売上金額(amount)の合計を算出します。

engine='pytnon'reset_indexの付与を忘れずに行いましょう。

>> queryメソッドの復習をする

>> groupbyメソッドの復習をする

1
2
df_sales_amount = df_receipt.query('not customer_id.str.startswith("Z")', engine='python').groupby('customer_id').agg({'amount':'sum'}).reset_index()
df_sales_amount
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
14

customer_id amount
0 CS001113000004 1298
1 CS001114000005 626
2 CS001115000010 3044
3 CS001205000004 1988
4 CS001205000006 3337
... ... ...
8301 CS051212000001 336
8302 CS051513000004 551
8303 CS051515000002 265
8304 CS052212000002 192
8305 CS052514000001 178
8306 rows × 2 columns

標準化を行うためにSrtandardScalerクラスのインスタンスを作成します。

>> クラスとインスタンスをシンプルに理解する

1
scaler = preprocessing.StandardScaler()

作成したインスタンスを用いて標準化を行います。処理の方法は以下のコードのように、標準化に変換するインスタンス(変換モデル)にdf_sales_amount[['amount]]のデータを用いて学習させます。

学習はfitを使用します。

1
2
scaler.fit(df_sales_amount[['amount']])
# 出力>> StandardScaler()

変換モデルに基づいて標準化処理を行い、標準化したデータを新たに作成するamount_ssというカラムに格納します。

1
2
df_sales_amount['amount_ss'] = scaler.transform(df_sales_amount[['amount']])
df_sales_amount
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
	customer_id	amount	amount_ss
0 CS001113000004 1298 -0.459378
1 CS001114000005 626 -0.706390
2 CS001115000010 3044 0.182413
3 CS001205000004 1988 -0.205749
4 CS001205000006 3337 0.290114
... ... ... ...
8301 CS051212000001 336 -0.812988
8302 CS051513000004 551 -0.733959
8303 CS051515000002 265 -0.839086
8304 CS052212000002 192 -0.865919
8305 CS052514000001 178 -0.871065
8306 rows × 3 columns

これで完了です。

第60問目: Min-Max正規化

P-060: レシート明細データフレーム(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、合計した売上金額を最小値0、最大値1に正規化して顧客ID、売上金額合計とともに表示せよ。ただし、顧客IDが”Z”から始まるのものは非会員を表すため、除外して計算すること。結果は10件表示させれば良い。

最小値を0、最大値を1となるようにデータを変換することをMin-Max正規化と言います。

Min-Max正規化を行う場合は、sklearn.preprocessing.MinMaxScalerクラスを使用します。

数式で表現すると以下のようになります。

本問を解きながら使い方を学んでいきましょう。

まずは顧客IDがZから始まるものを除外し、売上金額(amount)を顧客ID(customer_id)ごとに合計したデータ算出します。

1
2
df_sales_amount = df_receipt.query('not customer_id.str.startswith("Z")', engine='python').groupby('customer_id').agg({'amount':'sum'}).reset_index()
df_sales_amount
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
	customer_id	amount
0 CS001113000004 1298
1 CS001114000005 626
2 CS001115000010 3044
3 CS001205000004 1988
4 CS001205000006 3337
... ... ...
8301 CS051212000001 336
8302 CS051513000004 551
8303 CS051515000002 265
8304 CS052212000002 192
8305 CS052514000001 178
8306 rows × 2 columns

MinMaxScalerクラスのインスタンスを生成します。

1
scaler = preprocessing.MinMaxScaler()

作成したインスがん(変換モデル)をamountデータを用いて学習させます。

1
2
scaler.fit(df_sales_amount[['amount']])
# 出力>> MinMaxScaler()

MinMax正規化したデータを”amount_mm”というカラムに代入します。

1
2
df_sales_amount['amount_mm'] = scaler.transform(df_sales_amount[['amount']])
df_sales_amount.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	customer_id	amount	amount_mm
0 CS001113000004 1298 0.053354
1 CS001114000005 626 0.024157
2 CS001115000010 3044 0.129214
3 CS001205000004 1988 0.083333
4 CS001205000006 3337 0.141945
5 CS001211000025 456 0.016771
6 CS001212000027 448 0.016423
7 CS001212000031 296 0.009819
8 CS001212000046 228 0.006865
9 CS001212000070 456 0.016771

これで完成です。

まとめ: 正規化を学びました

本記事は、「【Python】正規化(z-score, Min-Max normalization)を実装 | データサイエンス100本ノック【問59〜60 回答】」というテーマでまとめました。

本記事で紹介した方法を元にデータサイエンティストとしての知見を深めていただければと思います。

なお、データサイエンティストに必要な知識は、TechAcademyのデータサイエンスコースでの学習がおすすめです。

>> [続き]第61〜62問の回答・解説を確認する

コメント