「Pythonで儲かるAIをつくる」実装補足

# はじめに
　「Pythonで儲かるAIをつくる」の著者です。
[Amazonリンク](https://www.amazon.co.jp/dp/B08F9P726T/)
[書籍サポートサイトリンク](https://github.com/makaishi2/profitable_ai_book_info/blob/master/README.md)
　何を隠そう、私は昔からプログラミングおたく※なもので、書籍のサンプルコードには相当こだわりがあるのですが、「Pythonで儲かるAIをつくる」では、何カ所か悔いの残る実装がありました。
　出版社の担当者とも相談し、ちゃんと動いているのだから正誤訂正ではないだろうといわれ、確かにその通りなので、こういう形で後悔を公開するに至った次第です。

※　コーディング経験のあるプログラム言語は以下のような感じ。他にも多分いくつかあると思います。
BASIC, Assembler(86系),FORTRAN, LISP, Prolog, C(C++は本当にかすかに), Assembler(HOST), APL, APL2, COBOL, REXX, Pascal(Delphi), VB, Java, Perl, PHP, Ruby, Swift, JavaScipt(+node.js), Python

# 4.4節　混同行列表示用関数

```py
y_test = [0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1]
y_pred = [0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1]

```
 
という正解値と予測値があったとき、次の関数を定義しておくと

```py3
# 混同行列表示用関数

def make_cm(matrix, columns):
    # matrix numpy配列
    
    # columns 項目名リスト
    n = len(columns)
    
    # '正解データ'をn回繰り返すリスト生成
    act = ['正解データ'] * n
    pred = ['予測結果'] * n
    
    #データフレーム生成
    cm = pd.DataFrame(matrix, 
        columns=[pred, columns], index=[act, columns])
    return cm
```

こんなコードで、きれいな形式の混同行列が表示できます、というのが、ここの内容でした。


```py
from sklearn.metrics import confusion_matrix
matrix = confusion_matrix(y_test, y_pred)

# make_cmを使った混同行列標示
cm = make_cm(matrix, ['良性', '悪性'])
display(cm)
```

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/b9c052ea-3f27-1868-d4a7-edb3832d2352.png' width=300>

　しかし、最新のscikit-learnでは、ほぼ同等のことが可能なライブラリができています。
好みの問題もありますが、これでいい場合は無理に関数を定義して使う必要はないです。
私としては「Predicted label」の位置が、下でなく、上にあれば文句がなかったのですが。。。



```py
# ライブラリのインポート
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.metrics import confusion_matrix
# 検証データの混同行列を出力
cm = confusion_matrix(y_pred=y_pred, y_true=y_test)
cmp = ConfusionMatrixDisplay(cm, display_labels=['良性', '悪性'])
cmp.plot(cmap=plt.cm.Blues)
plt.show()
```

結果サンプル

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/2c194fea-303a-119f-f566-cdfda7e3a726.png' width=300>



# 5.1節　(4.2節)ダミー変数化

　多値コードをダミー変数化する実装として以下を示しています。

```py
# get_dummies関数でカテゴリ値をOne-Hotエンコーディング

# 項目をOne-Hotエンコーディングするための関数
def enc(df, column):
    df_dummy = pd.get_dummies(df[column], prefix=column)
    df = pd.concat([df.drop([column],axis=1),df_dummy],axis=1)
    return df

df_all2 = df_all.copy()
df_all2 = enc(df_all2, '職業')
df_all2 = enc(df_all2, '婚姻')
df_all2 = enc(df_all2, '学歴')
df_all2 = enc(df_all2, '連絡手段')
df_all2 = enc(df_all2, '前回販促結果')
```

　 書籍オリジナルよりシンプルな実装は下記になります。

```
cols = ['職業', '婚姻', '学歴', '連絡手段', '前回販促結果']
df_all2 = df_all.copy()
df_all2 = pd.get_dummies(df_all2, columns=cols)
```


# 5.4節　横持ち化
 タテ持ちのデータをヨコ持ち化するためのコードとして書籍では以下を示しています。

```py
# 商品番号を列に移動 (unstack関数の利用)
w2 = w1.unstack().reset_index().fillna(0).set_index('発注番号')
```

 このコード、よく見直すと　reset_indexと set_indexはまったく逆の操作をする関数で、２つ実行するならそれは両方を呼び出さないのと同じ結果になるはずです。その実装が下記。

```py
# 商品番号を列に移動 (unstack関数の利用)
w2 = w1.unstack().fillna(0)
```

 これで元のコードとまったく同じ動きになりました。