乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

プログラミング

今回はたった2行で
機械学習の精度検証が出来ちゃう
Lazypredictを試してみました

解説動画はこちら


このライブラリは
機械学習用のモデルを自動作成して
複数のモデルを比較してくれます

これがgithubです
Lazypredict

ドキュメントとしては
それほど情報量が多くないようです

コードなどもシンプルで
かなり使いやすい印象ですね


GoogleColabで動かせるので
使いたい方はコードを参考にしてみてください。

まず最初はライブラリのインストールです
# ライブラリのインストール
pip install lazypredict
30秒くらいでインストールも終わります。

GoogleColabなら追加のインストールが
無くても動くと思います。

このライブラリは
数値を予測する回帰モデルと
種別を予測する判別モデル
2種類の機械学習モデルの比較を行えます



最初は判別モデルをみてみましょう
データはscikit-learnのデータセットを使います

load_wine
ワインの品種に関するデータセットで
14列178個のデータがあり
3クラス分類で予測します


説明変数
alcohol アルコール濃度
malic_acid リンゴ酸
ash 灰
alcalinity_of_ash 灰のアルカリ成分
magnesium マグネシウム
total_phenols 総フェノール類量
flavanoids フラボノイド(ポリフェノールらしい)
nonflavanoid_phenols 非フラボノイドフェノール類
proanthocyanins プロアントシアニジン(ポリフェノールの一種らしい)
color_intensity 色の強さ
hue 色合い
od280/od315_of_diluted_wines ワインの希釈度合い
proline プロリン(アミノ酸の一種らしい)

目的変数
ワインの品種

こんな感じのデータです
読み込みのコードはこちら
from sklearn import datasets
import pandas as pd
df = datasets.load_wine(as_frame=True).frame

print('行列数 : ' , df.shape)
print('ターゲットの種別数 : ' , df['target'].nunique())
df.head()

これでデータが用意できたので
次は学習データの分割です
トレーニング7 , テストサイズ3で分割します
# 学習データの分割
from sklearn.model_selection import train_test_split
X = df.iloc[0: , 0:-1]
Y = df['target']

# トレーニング7 , テストサイズ3で分割
x_train, x_test, y_train, y_test = train_test_split(X , Y , test_size=0.3 , random_state=0)
x_train.shape, x_test.shape, y_train.shape, y_test.shape
((124, 13), (54, 13), (124,), (54,))


最後にlazypredictで
予測モデルの作成です

分類モデルを複数自動で生成し
その精度検証の結果と
予測結果を出してくれます

モデルの作成、検証部分は2行でいけます
分類モデルの検証はLazyClassifierを使います
# lazypredictのインポート
import lazypredict
# 回帰予測
#from lazypredict.Supervised import LazyRegressor
# 分類問題
from lazypredict.Supervised import LazyClassifier

# 予測モデルの作成(たったの2行だけ)
clf = LazyClassifier(verbose=1,ignore_warnings=True,predictions=True)
models , predictions = clf.fit(x_train , x_test , y_train , y_test)

最後の行の変数
models , predictions
に精度検証の結果と
予測結果が格納される仕組みです


作成した予測モデルの比較を見てみましょう

# モデルの比較
models
スクリーンショット 2022-10-01 16.01.17

こんな感じで予測モデルを一気に検証してくれます


テストデータの予測結果も見てみましょう
# テストデータ で予測
predictions
スクリーンショット 2022-10-01 16.02.36

列方向は各モデルで
行がテストデータです


回帰モデルも同様に試してみましょう

load_boston
ボストン住宅価格のデータです
from sklearn import datasets
import pandas as pd

data = datasets.load_boston()
boston_df = pd.DataFrame(data=data["data"] , columns=data["feature_names"])
boston_df['MEDV'] = data["target"]

print('行列数 : ' , boston_df.shape)
print('ターゲットの平均値 : ' , boston_df['MEDV'].mean())
boston_df.head()

学習データの分割も同様です
# 学習データの分割
from sklearn.model_selection import train_test_split
X = boston_df.iloc[0: , 0:-1]
Y = boston_df['MEDV']

# トレーニング7 , テストサイズ3で分割
x_train, x_test, y_train, y_test = train_test_split(X , Y , test_size=0.3 , random_state=0)
x_train.shape, x_test.shape, y_train.shape, y_test.shape
回帰モデルの検証も2行でいけますが
回帰の場合はLazyRegressorを使用します

# lazypredictのインポート
import lazypredict
# 回帰予測
from lazypredict.Supervised import LazyRegressor
# 分類問題
#from lazypredict.Supervised import LazyClassifier

# 予測モデルの作成(たったの2行だけ)
reg = LazyRegressor(verbose=1,ignore_warnings=True,predictions=True)
models , predictions = reg.fit(x_train , x_test , y_train , y_test)
# モデルの比較
models
スクリーンショット 2022-10-01 15.42.01

こんな感じの結果になりました



まとめ


データを突っ込めばどの手法の精度が高くなるのかを
結構な速さで出してくれるので
初めて予測モデルを作るデータには
最適かもしれません


AutoMLで似たようなものに
PyCaretというのが有りますが
Lazypredictの方がバグが出なくて
良いかもしれないなーと思いました

検証をパパッとやりたい方には
かなり良いライブラリかと思いますので
試したい方はコードを参考にしていただければと思います

それでは

今回は文字列の検索をする際に役立つ
正規表現についてです。


解説動画はこちら




正規表現とは

さて正規表現とは何でしょうか?

正規表現は
「いくつかの文字列を一つの形式で
表現するための表現方法」です

メタ文字と呼ばれる記号を用いて
複数の文字列を1つのパターンで
表現していきます。

メタ文字には次のようなものがあります。


. ^ $ * + ? | ( ) [ ]


正規表現のパターンのルールは細かく
一気に覚えるのが大変です。

基本的なものだと
次のようなものがあります。

a

定義済みの正規表現パターンは
次のようなものがあります。

b


特定位置の正規表現パターンだと
次のようなものがあります。

c


これらを組み合わせて
色々な文字列を1つのパターンで表します。


Python言語で正規表現を使う方法


Pythonで正規表現を使うには
reライブラリを用います

ライブラリを読み込み
正規表現パターンを指定して
reライブラリの検索メソッドで
検索対象の文字列からパターンを探します。
import re

pattern = "正規表現パターン"
text = "検索対象の文字列"

re.検索メソッド(pattern , text)


reライブラリの検索メソッドは
結構たくさんあります。

まずはsearchメソッドです。

これは正規表現に当てはまる箇所を
位置で返します。

結果はmatchオブジェクトになるので
この中から、必要なものを取り出す形になります。
import re

pattern = "[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+"
text = '私のメールアドレスはotupy@otupy.comです'

# 正規表現に当てはまる箇所を位置で返す
result = re.search(pattern , text)
print(result)
print(result.span())
print(result.group())
print(re.search(pattern , text).group())
<re.Match object; span=(10, 25), match='otupy@otupy.com'>
(10, 25)
otupy@otupy.com
otupy@otupy.com



次はfindallメソッドです
これは正規表現に当てはまる部分を
リストで返します。

import re

pattern = "[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+"
text = '私のメールアドレスはotupy@otupy.comです'

# 正規表現に当てはまる部分をリストで返す
results = re.findall(pattern , text)
print(results)
['otupy@otupy.com']



次はsubメソッドです
これはパターンに当てはまる部分を
他の文字列に置換することができます。
import re

pattern = "[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+"
text = '私のメールアドレスはotupy@otupy.comです'

# 正規表現で文字列を置換する
result = re.sub(pattern , 'mail_address', text)
print(result)
私のメールアドレスはmail_addressです



最後はsplitメソッドです
これはパターンに当てはまる部分で
文字列を分割してリスト化します。
import re

pattern = "[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+"
text = '私のメールアドレスはotupy@otupy.comです'

# 正規表現に当てはまる部分で分割する
results = re.split(pattern , text)
print(results)
['私のメールアドレスは', 'です']


reの検索メソッドは、目的に応じて
使い分けるのが良いでしょう。




正規表現のパターンサンプル

ここからは、正規表現の
パターンサンプルを見ていきましょう。

検索メソッドとしては「findall」を主に使用します。

a から始まって z で終わる 3 桁の文字列
pattern = "a.z"
text = 'abz,abc,cbz'

results = re.findall(pattern , text)
print(results)
['abz']


a から始まって z で終わる 3 桁以上の文字列
pattern = "a.+z"
text = 'abz,abc,cbz'

results = re.findall(pattern , text)
print(results)
['abz,abc,cbz']


4 桁の半角数字
pattern = "\d{4}"
text = '123 , 1234 , 23456'

results = re.findall(pattern , text)
print(results)
['1234', '2345']


4 ~ 10 桁の半角数字 (最長一致)
pattern = "\d{4,10}"
text = '123 , 1234 , 23456 , 334455667788'

results = re.findall(pattern , text)
print(results)
['1234', '23456', '3344556677']


桁区切りのカンマ付数字
pattern = "(?:^| )(\d{1,3}((?:,\d{3})*))(?=$| )"
text = '123,456 , 334455667788  1,234'

results = re.findall(pattern , text)
print(results)
[('123,456', ',456'), ('1,234', ',234')]


携帯電話番号
pattern = '[\(]{0,1}[0-9]{2,4}[\)\-\(]{0,1}[0-9]{2,4}[\)\-]{0,1}[0-9]{3,4}'
text = '携帯番号は 090-1234-5678 です 他は090-9876-4321'

results = re.findall(pattern , text)
print(results)
['090-1234-5678', '090-9876-4321']


日付
pattern = "[0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2}"
text = '今日は2022/10/1です 2023/01/31'

results = re.findall(pattern , text)
print(results)
['2022/10/1', '2023/01/31']

pattern = r"[0-9]{4}年[0-9]{2}月[0-9]{2}日"
text = '今日は2022年01月10日です'

results = re.findall(pattern , text)
print(results)
['2022年01月10日']


日付などはちゃんと日付の妥当性も考えると
もう少し複雑なパターンを考える必要が出てきます。


まとめ
正規表現はどんなプログラム言語でも
共通的に使える表現なので覚えておくと便利です。

正規表現を作り込めば
複雑なコードを書かなくても
正規表現で妥当性のチェックを行うことができ
短いコードで良くなります。

ググれば、正規表現の様々なパターンを
探すことができるので
自分の作りたいパターンに似たものを
流用しながら作るのが良いと思います。

覚えるのが少し大変ですが
覚える価値は有るかと思いますね。

今回はここまでです
それでは。


今回はテキストから画像を自動生成する
stable-diffusionをGoogle Colabで試してみました

解説動画はこちら






さて、こちら
最近公開されたようなのですが
テキストから画像を生成してくれるという
優れものです

使えるようにするには
少しコツがいるので手順を紹介します。

デモサイト



コードを動かすために必要な作業

1.Hugging Faceのアカウント作成(要メールアドレス)

最初はhuggingfaceというサイトのアカウントが必要です
SignUpからメアドとパスワードで登録しましょう。


2.来たメールで認証確認

登録したらメールが来ると思うので
リンクをクリックして認証確認をします。


3.stable-diffusionのModel cardの使用申請をする
申請先

次にこのライブラリを使うためには
Model cardというものの使用許可がいるため
申請をする必要があります。

リンクにアクセスして
チェックを入れて
Access repositoryをクリックします。


4.Access Tokenを取得

その後、Tokenの作成画面に遷移し
「New token」をクリックして
適当な名前で「token」を作成します。
スクリーンショット 2022-08-27 14.34.32

出来上がったら、コピーボタンがあるので
それをコピーします。



ここからはGoogle Colabの設定です。

5.Google Colabのランタイムの変更

CPUでは動かないので、ランタイムを設定変更します。

「ランタイム」から「ランタイムタイプの変更」
スクリーンショット 2022-08-27 15.45.44
ハードウェアアクセラレーターを
「None」から「GPU」へ変更します。



6.Access Tokenをコードに入力して実行する

最後に次のコードをコピペして
Tokenを打ち込んで実行します。

そうするとコード類のセットアップが走り
2-3分すると終わります。

#@title 事前セットアップ
 
# 必要なライブラリのインストール
!pip install diffusers==0.2.4 transformers scipy ftfy
 
# アクセス・トークンを設定
token = ""#@param {type:"string"}

# パイプラインを構築
from diffusers import StableDiffusionPipeline
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", use_auth_token=token)
pipe.to("cuda")



あとは下記のコードをコピペして
英文のテキストを入力して画像を生成しましょう。
#@title 画像を生成する
 
# 画像生成
prompt = "A small cabin on top of a snowy mountain in the style of Disney, artstation" #@param {type:"string"}
img = pipe(prompt)["sample"][0]
 
# 画像の保存
img_name = prompt.replace(' ','_')
img_path = img_name + '.png'
img.save(img_path)

# 画像の表示
from IPython.display import Image,display
display(Image(img_path))

画像は画像保存で指定したパスに
保存されます。

画像作成時のポイントとして
・英文でないとダメです
・画風(スタイル)を指定できます


今回使用した英文の例です

A high tech solarpunk utopia in the Amazon rainforest

A pikachu fine dining with a view to the Eiffel Tower

A mecha robot in a favela in expressionist style

an insect robot preparing a delicious meal

A small cabin on top of a snowy mountain in the style of Disney, artstation

A_high_tech_solarpunk_utopia_in_the_Amazon_rainforest
A_pikachu_fine_dining_with_a_view_to_the_Eiffel_Tower
A_mecha_robot_in_a_favela_in_expressionist_style

結構それなりに、いい感じに出来ていると思います。

画像の生成には30秒ほどかかり
Google ColabのGPU使用は
無料版だと12時間ほどかと思うので
結構な枚数は作成できるんじゃないかと思います。

ちょっとしたイラストなんかは
自動で生成出来てしまいますね。

やりたい方は試してみてくださいね
それでは。

今回はセイバーメトリクスについて
少し調べてみました。


解説動画はこちら



さて
今回はセイバーメトリクスについてです
知らない方もいるかもしれないので
簡単な説明ですが

セイバーメトリクスとは
野球においてデータを
統計学的見地から客観的に分析し
選手の評価や戦略を考える
分析手法のことです。

ざっくり考えると
勝つためにデータ分析しましょう
ってことですね。

なので、今回は
勝利に貢献する指標を
見つけてみようと思います。

まず、データに関しては
こちらのサイトのデータを参考にしています。

プロ野球データFreak



さて、チームの成績データを見てみましょう。

TSVやCSVに取得したデータを
まとめていれば、ファイルの読み込みが出来ます。

ファイルの読み込み
import pandas as pd
team_df = pd.read_table('baseball_all_team_stats2.tsv')
team_df.shape
(168, 51)



今回使用するのは、こんな感じのデータです。
スクリーンショット 2022-08-20 17.56.12

2009 - 2022年8月20日までのデータです。



さて次は、最近のリーグ成績を見てみましょう。

こんな感じのコードで時系列での
成績をまとめることが出来ます。

順位(Y軸)は反転させておくと
いい感じになります。

import matplotlib.pyplot as plt
import seaborn as sns

# セリーグ
se_league = team_df[team_df['リーグ']=='セリーグ']
g = sns.relplot(x='年度', y='順位', hue='チーム' , data=se_league, kind='line')
g.fig.axes[0].invert_yaxis()
g.fig.set_figwidth(12)
download

こちらはパリーグです
download-1

これで見ると、セリーグは順位変動が激しく
パリーグは特にソフトバンクが強いですね
ここ最近は5位以下になったことが無さそうです


次は勝率を見てみましょう。

2009 - 2022までの全試合での全チームの勝率
groupby  = team_df[['チーム','試合','勝利','敗北']].groupby('チーム').sum()
groupby['勝率']  = groupby['勝利'] / groupby['試合']
groupby.sort_values('勝率',ascending=False)
スクリーンショット 2022-08-20 17.57.07

パリーグはソフトバンク
セリーグは巨人
の勝率が良いですね

とはいえ、べらぼうに差があるわけでは
無いようです。


次はこの勝利数に貢献する指標を見てみましょう。


勝利数に貢献しそうな指標は何か?
target_kpi = ['得点', '平均得点', '失点', '平均失点', '打率', '本塁打','防御率', '安打', '出塁率', '長打率', 'OPS']

for kpi in target_kpi:
    tmp_df = team_df[['チーム','勝利'] + [kpi]]
    print(kpi , '相関係数 : ' , tmp_df.corr().iloc[1,0])
    g=sns.jointplot(x='勝利', y=kpi, data=tmp_df,kind='reg')
    g.fig.set_figwidth(3)
    g.fig.set_figheight(3)
    plt.show()
スクリーンショット 2022-08-20 17.57.24

# 相関係数のみ計算する
corrs = {}
for kpi in target_kpi:
    tmp_df = team_df[['チーム','勝利'] + [kpi]]
    corrs[kpi] = tmp_df.corr().iloc[1,0]

for k,v in sorted(corrs.items() , reverse=True , key=lambda x:x[1]):
        print(k,v)
得点 0.6752214591815026
安打 0.6266412461266061
打率 0.5737515556643754
OPS 0.5707190644752489
出塁率 0.5601397549262012
平均得点 0.5484023969333554
長打率 0.5206867389057273
本塁打 0.4614069008549154
失点 -0.03810712231263921
平均失点 -0.28881452409175656
防御率 -0.30572213281469424



勝利数に貢献しそうな指標としては
得点が一番関係性が高そうです。

野球のルールの性質上
相手チームよりもたくさん点を取った方が勝つので
得点数は勝利に貢献するのは当たり前でしょうね。


次はこの得点に貢献する指標を見てみましょう。

得点に貢献しそうな指標は?
target_kpi = ['打率', '本塁打', '安打', '出塁率', '長打率', 'OPS']

corrs = {}
for kpi in target_kpi:
    tmp_df = team_df[['チーム','得点'] + [kpi]]
    corrs[kpi] = tmp_df.corr().iloc[1,0]

for k,v in sorted(corrs.items() , reverse=True , key=lambda x:x[1]):
        print(k,v)
OPS 0.8708254335866881
長打率 0.8159000896409998
安打 0.8097657028521518
出塁率 0.8054269840935689
本塁打 0.7637663066912697
打率 0.7457514146368397


平均得点だと
OPS 0.9567899908827453
長打率 0.9145865090996436
出塁率 0.8454041544924719
本塁打 0.7794856511615135
打率 0.7363115009552308
安打 0.5156269035543274


OPSは
得点数だと0.870
平均得点だと0.956
という高い相関係数になります。


OPSはOn-base plus sluggingの略で
野球において打者を評価する指標の1つで
出塁率と長打率を足し合わせた値になります。


こういった指標を一つ一つ検証し
どんな指標が貢献するのかを探るのも
セイバーメトリクスの醍醐味かと思います。


今回は勝利数に関しては得点

得点に関してはOPSが
高い貢献度があることが分かりました。

次回はこの、OPS周りを
詳しく深掘りしていきたいと思います。

今回はここまでです
それでは。


 

今年の夏は暑いですねー
毎日アイスを食べたくなりますね

そんなわけでアイスの価格のデータを
見てみることとしました。


解説動画はこちら



E-statに小売物価統計調査(動向編)2021年
というのが有って


結果表 1 調査品目の月別価格及び年平均価格
【都道府県庁所在市及び人口15万以上の市】
「1701 ようかん」 ~ 「1797 弁当」
というのが今回使用したデータです。

アイスは「ハーゲンダッツ・バニラ」
(295円,税込318円)を基準にしている
ようでした。

しかしe-statのデータはこんな感じで
aice

エクセルファイルになっていますが
まだエクセルなのは0点だとしても

ヘッダーに文章が有ったり
縦積みしなければいけない所を
横積みにしていたりと
相当なゴミっぷり-100点です。

なので、2回の整形、加工が必要でした。

まずはこのエクセルから
必要な部分だけをコピーして
TSV形式で保存しなおします。

aice.tsv

次はこのデータの横積みされている所から
縦積みに直します。

こんな感じのコードで整形です。
data = []
with open('aice.tsv') as _f:
    for row in _f:
        rows = row.replace('\n','').split('\t')
        data.append(rows)

data2 = []
for rows in data[2:]:
    name = rows[1]
    for i,t in enumerate(rows[4:]):
        tmp = [name , '{0:02}月分'.format(i+1) , int(t)]
        data2.append(tmp)


さて、このデータを見ていきましょう。
データフレームに読み込みします。
import pandas as pd

df = pd.DataFrame(data2 , columns=['市町村','月','価格'])

df.shape
(972, 3)


平均価格が安い地域はどこか?
df2 = df.groupby('市町村').mean('価格').sort_values('価格')

df2
スクリーンショット 2022-08-13 16.59.52


最安値の地区は?
df3 = df.sort_values('価格').head()

df3
スクリーンショット 2022-08-13 17.00.12


最安地域の分布
import seaborn as sns
from matplotlib import pyplot as plt

df4 = df[df['市町村'].isin(df2.index[0:10])]

plt.figure(figsize=(10,5))
sns.boxplot(x='市町村',y='価格', data=df4,order=df2.head(10).index)
plt.title('')
plt.show()
download


これで見ると
全国の地域の中で
最も安い値をつけたのは「浦安市」
平均価格でも「浦安市」が安くなっていました。

アイスを安く買いたければ
「浦安市」のスーパーが
安い可能性が高いですね。

でも、なんでこんなに安いんですかね?
ミッキーに脅されていたりしたら
面白いんですけどね

ちなみに
ハーゲンダッツの小売は300円くらいなので
200切っていたら相当な買いですねー

自分は安い時にまとめ買いしてます。

今年は消費量が多いので
データから家計を守るのも
大事と思います。

それでは。

このページのトップヘ