knaka Tech-Blog

AI, IoT, DIYエレクトロニクス, データサイエンスについて投稿予定です。

機械学習 + flask WEBアプリの実装

index:

概要

前回の、flask関連となりますが。機械学習
軽量web フレームワークのflaskで、
webアプリの実装を行いました。

=> 機械学習は、前回の家賃予測の機能を
実装し、学習済みの modelファイルから
予測を出力しています。
機械学習処理は、事前に完了させておく形です

=> 言語的には、全てpython 構成となります。

環境

python 3.5
flask

=> 今回は、DBは使用していません。

Github

github.com



サンプルの、プロジェクトです

機能

・予測条件入力
不動産の条件を、入力し。
実行します。


f:id:knaka0209:20190125184329p:plain

・結果、金額の出力

f:id:knaka0209:20190125184350p:plain

まとめ

web画面から、自作した機械学習ディープラーニング機能が
使用できるようになり。便利ですね!!
さらに、応用して行きたいと思います。

flask + mysql DBアプリの実装

index:

概要

python 軽量web フレームワークのflask
と、mysql DB連携を試してみました。

環境

python 3.5
flask

準備

mysql関係で、O/Rマッピング等の
ライブラリを追加

pip install sqlalchemy
pip install flask-sqlalchemy PyMySQL

ファイル構成

上記のチュートリアルと、ほぼ同じですが。
下記となります、dbモデルは、 models の下に配置した場合です。

#└─flaskr
    ├─models
    │  └─__pycache__
    ├─static
    └─templates

github

https://github.com/kuc-arc-f/flask_sample2

サンプルの、プロジェクトです
先に、mysqlのDB作成。必用なテーブル作成が
必用です。

設定

DB接続
・ config.py
musqlの、DB名、ユーザー、パスワード、ホストの設定
接続ユーザーは、事前に追加しておきます。

SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://db_user:password@localhost/flask_db?charset=utf8'
SECRET_KEY = 'secret key'

・__init__.py
config.py の読み込み等

# coding: utf-8

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config.from_object('flaskr.config')

db = SQLAlchemy(app)

import flaskr.views

・manage.py
起動する、ファイル。デバックモードの場合。( port=5000 )

from flaskr import app
app.run(host='127.0.0.1', port=5000, debug=True)

デモ、チュートリアルのアプリ

必用なテーブル作成等を行い、アプリを起動します。

f:id:knaka0209:20190125141329p:plain

=>必用な値を入力し、[share] ボタンを押すと、
DBに登録され、下段リスト表示できました。

予測問題、kaggle: PUBG Finish Placement Prediction

index:

概要

kaggleチャレンジで、 PUBG Finish Placement Prediction
予測問題

コンペ

https://www.kaggle.com/c/pubg-finish-placement-prediction


ケームの、勝率的な値の、予測らしいですね

環境

python 3.5
scikit-learn
numpy
matplotlib


テストは、kaggle kernel など使用。

学習データ

kaggle の上記ページから、
学習データ等を、コピーします。



目的変数:
winPlacePerc


説明変数:
 ゲームの戦闘に関するデータ、

matchTypeは、カテゴリ変数らしく。
ダミー変数で、数値化しました。

=> 学習データは、440万件程で、多めで
 メモリ的に厳しかったので、kernel で結果を出力しました。

前処理

・欠損値は、削除
・上記のダミー変数の、変換
 など

・ 今回は、重回帰分析で、機械学習の処理しました。

#
def conv_dammy_mat(df):
    head_mat = "matchType"
    for item in df.columns:
        df=  df.rename(columns={ item : head_mat +"_"+ item} )
    return df
#
def conv_xdata(df):
    df =df.drop("Id", axis=1)
    df =df.drop("groupId", axis=1)
    df =df.drop("matchId", axis=1)
    df =df.drop("matchType", axis=1)
    return df

# 学習データ
global_start_time = time.time()

train = pd.read_csv("train-tmp.csv") # Reading data
test  = pd.read_csv("test-tmp.csv") # Reading data
# 
train = train[: 10000]
test  = test[: 10000]
#train_sub = train[: 10000]
#train_sub.to_csv('train-tmp.csv', index=False)

train.dropna(inplace=True)
#print( train.isnull().sum() )
print( train.isnull().any() )
train.info()
#quit()

# conv, dummy val
train_mat = pd.get_dummies(train["matchType"]) 
#train= train[: 10000]
train_mat =conv_dammy_mat(train_mat )
print(train.shape )
print(train_mat.shape )

#
test_mat = pd.get_dummies(test["matchType"]) 
#train= train[: 10000]
test_mat =conv_dammy_mat(test_mat )
print(test.shape )
print(test_mat.shape )

#quit()
#print( len(train_mat.columns ))
#print( len(test_mat.columns ))
#quit()
#merge
train_mat["Id"] = train["Id"]
train_all= pd.merge( train , train_mat )
test_mat["Id"] = test["Id"]
test_all= pd.merge( test , test_mat )
#quit()
#
y_train =train_all['winPlacePerc']
y_data = y_train
#train_all.info()
x_train =train_all
x_train =conv_xdata(x_train )
x_train =x_train.drop("winPlacePerc", axis=1)

x_test = test_all
x_test = conv_xdata(test_all )
#
print(x_train.shape ,y_train.shape )
print(x_test.shape  )

結果の提出

スコアは、0.0891 ほど。
ランキング順位は表示されず。でした

f:id:knaka0209:20190122183317p:plain

参考コード

github.com

予測問題、kaggle: New York City Taxi Trip Duration

index:

概要

kaggleチャレンジで、 New York City Taxi Trip Duration
予測問題

コンペ

https://www.kaggle.com/c/nyc-taxi-trip-duration

タクシーの、乗車時間を予測する。問題らしいですね

環境

python 3.5
scikit-learn
numpy
matplotlib


テストは、kaggle kernel など使用。

学習データ

kaggle の上記ページから、
学習データ等を、コピーします。



目的変数:
trip_duration(乗車した時間。秒数)

説明変数:
乗車した場所。緯度、経度、
乗車した日時 など

=> 説明変数は、さほど多くないようですが。
 学習データの件数が多く、140万件以上
 で、作業PCで 学習時でもメモリ不足
 の可能性が。予測できたので、kernel で評価し、結果出力しました

前処理

・store_and_fwd_flag :カテゴリ変数の変換
・pickup_datetime : datetime型に変換。
・pickup_dt :pickup_datetimeの最小値からの差分、秒数
・lat_diff : 移動した latitude 距離
・lon_diff :移動した longitude 距離


=> 今回は、重回帰分析で、機械学習の処理しました。

  
# データ加工・処理・分析モジュール
import numpy as np
import numpy.random as random
import scipy as sp
from pandas import Series, DataFrame
import pandas as pd

# 可視化モジュール
import matplotlib.pyplot as plt
import matplotlib as mpl
# 機械学習モジュール
import sklearn
from sklearn import linear_model
import pickle
import time 

#
def correct_data(taxi_data):
    taxi_data.store_and_fwd_flag = taxi_data.store_and_fwd_flag.replace(['N', 'Y'], [0, 1])
    return taxi_data

# 学習データ
global_start_time = time.time()
train = pd.read_csv("../input/train.csv") # Reading data
test  = pd.read_csv("../input/test.csv")  # Reading data

# 
#train= train[: 10000]
print(train.shape ,test.shape )
#quit()

#test  = pd.read_csv("../input/test.csv")  # Reading data
train = train[ train['trip_duration'] < 1000000]
# convert
train= correct_data(train)
test = correct_data(test )
#for df in (train_data,test_data):
#quit()

for df in (train, test ):
    df['pickup_datetime'] = pd.to_datetime(df['pickup_datetime'], format='%Y-%m-%d %H:%M:%S')
    df['pickup_dt'] = (df['pickup_datetime'] - df['pickup_datetime'].min()).dt.total_seconds()
    df['lat_diff'] = df['pickup_latitude'] - df['dropoff_latitude']
    df['lon_diff'] = df['pickup_longitude'] - df['dropoff_longitude']

col_name = ["vendor_id","passenger_count", "pickup_longitude", "pickup_latitude"
          , "dropoff_longitude", "dropoff_latitude","lat_diff","lon_diff"
           ,"pickup_dt" ]
train_sub  =train[col_name]
test_sub   =test[col_name]
x_test =test_sub
x_train =train_sub
y_train =train['trip_duration']
print( x_train.shape, y_train.shape )
print( x_test.shape )

結果の提出

スコアは、0.86 ほど。
ランキング順位は表示されず。でした

f:id:knaka0209:20190109145605p:plain

予測問題、kaggle House Prices: Advanced Regression Techniques

index:

概要

予測問題で、kaggle House Prices: Advanced Regression


https://www.kaggle.com/c/house-prices-advanced-regression-techniques

今回は、sklern 重回帰分析で進める事にしてみました。

環境

python 3.5
scikit-learn
numpy
matplotlib

学習データ

kaggle の上記ページから、
学習データ等を、コピーします。


train.csv
test.csv


目的変数:
不動産の価格

説明変数:
不動産の条件、年数など 79種類ほど

コード

参考ページ様を参考に
・説明変数の項目数は、多目にしました
・欠損値の対応
・カテゴリ変数は、ダミー変数も使用
・train, test データは、ダミー変数の変換後に
 分割
・提出用のCSV出力

import numpy as np
import numpy.random as random
import scipy as sp
from pandas import Series, DataFrame
import pandas as pd

# 可視化モジュール
import matplotlib.pyplot as plt
import matplotlib as mpl
# 機械学習モジュール
import sklearn
from sklearn import linear_model
import pickle
import time 

#
def conv_dats(df):
    #欠損値の補完
    df["PoolQC"].fillna('NA', inplace=True)
    df["MiscFeature"].fillna('None', inplace=True)
    df["Alley"].fillna('NA', inplace=True)
    df["Fence"].fillna('NA', inplace=True)
    df["FireplaceQu"].fillna('NA', inplace=True)
    df["GarageQual"].fillna('NA', inplace=True)
    df["GarageFinish"].fillna('NA', inplace=True)
    df["GarageCond"].fillna('NA', inplace=True)
    df["GarageType"].fillna('NA', inplace=True)
    df["BsmtCond"].fillna('NA', inplace=True)
    df["BsmtExposure"].fillna('NA', inplace=True)
    df["BsmtQual"].fillna('NA', inplace=True)
    df["BsmtFinType2"].fillna('NA', inplace=True)
    df["BsmtFinType1"].fillna('NA', inplace=True)
    df["MasVnrType"].fillna('None', inplace=True)
    #
    df["GarageYrBlt"].fillna(0, inplace=True) 
    df["MasVnrArea"].fillna(0, inplace=True)
    df["BsmtHalfBath"].fillna(0, inplace=True)
    df["BsmtFullBath"].fillna(0, inplace=True)
    df["TotalBsmtSF"].fillna(0, inplace=True)
    df["BsmtUnfSF"].fillna(0, inplace=True)
    df["BsmtFinSF2"].fillna(0, inplace=True)
    df["BsmtFinSF1"].fillna(0, inplace=True)
    df["GarageArea"].fillna(0, inplace=True)
    df["GarageCars"].fillna(0, inplace=True)
    #
    df["MSZoning"].fillna('RL', inplace=True)
    df["Functional"].fillna('Typ', inplace=True)
    df["Utilities"].fillna("AllPub", inplace=True)
    df['SaleType']    = df['SaleType'].fillna(df['SaleType'].mode()[0])
    df['Exterior2nd'] = df['Exterior2nd'].fillna(df['Exterior2nd'].mode()[0])
    df['Exterior1st'] = df['Exterior1st'].fillna(df['Exterior1st'].mode()[0])
    df['KitchenQual'] = df['KitchenQual'].fillna(df['KitchenQual'].mode()[0])
    df['Electrical']  = df['Electrical'].fillna(df['Electrical'].mode()[0])
    #
    f = lambda x: x.fillna(x.mean())
    df["LotFrontage"] = df.groupby("Neighborhood")["LotFrontage"].transform(f)
    return df

# 学習データ
global_start_time = time.time()
train_data = pd.read_csv("train.csv" )
test_data = pd.read_csv("test.csv" )
#print( train_data.shape )
#print( train_data.head() )

#print(train_data["Id"][: 10])
train_sub = train_data.drop("Id", axis=1)
test_sub  = test_data.drop("Id", axis=1)

# 目的変数
y_train = train_sub["SalePrice"]
# 説明変数に "xx" 以外を利用
train_sub = train_sub.drop("SalePrice", axis=1)

#学習用データとテストデータを一度統合する
df_all = pd.concat((train_sub , test_sub)).reset_index(drop=True)
print(df_all.shape )
df_all=conv_dats(df_all)
#quit()

tmp=df_all.isnull().sum()[ df_all.isnull().sum() != 0].sort_values(ascending=False)
#print(tmp)
#One Hot Encoding
df_all = pd.get_dummies(df_all)
print( df_all.shape )
ntrain = train_sub.shape[0]
x_train = df_all[:ntrain]
x_test  = df_all[ntrain:]

print( x_train.shape,  y_train.shape )
print( x_test.shape )
#quit()

# モデルのインスタンス
model = linear_model.LinearRegression()
# fit
clf = model.fit( x_train ,y_train)
print("train:",clf.__class__.__name__ ,clf.score(x_train,y_train))
#print("test:",clf.__class__.__name__ , clf.score(X_test,y_test))   

評価

train.csv の価格と、予測した価格の比較
f:id:knaka0209:20190101151407p:plain

参考のコード


github.com


.

ディープラーニングで、予測問題 家賃の予測(2) ネットワーク層の変更。

index:

概要

以前の ディープラーニングの予測問題の関連となります
ネットワーク層を増やして、精度のテスト行いたいと思います。
・ネットワーク構成、層の数は、タイタニック問題と似ていますが
 予測問題用のモデルとなります。

環境

python : 3.5.2
numpy
pandas


テストは、google colab など

学習データ

・目的変数
家賃

・説明変数
敷金、築年数 など。

コード

ニューラルネットの層数
隠れ層 :5
入力層 :1
出力層 :1
・7層のネットワーク


ニューロンの数
入力: 5(説明変数 の数)
隠れ層: 各100
出力層:1

import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import numpy.random as random
import scipy as sp
from pandas import Series, DataFrame
from sklearn.model_selection import train_test_split
import pandas as pd
import matplotlib.pyplot as plt
import time

from optimizer import SGD, Adam
from deep_price_net import DeepPriceNet

#
# 学習データ
global_start_time = time.time()
wdata = pd.read_csv("data.csv" )
wdata.columns =["no", "price","siki_price", "rei_price" ,"menseki" ,"nensu" ,"toho" ,"madori" ,"houi" ,"kouzou" ]
#print(wdata.head() )
#quit()

# conv=> num
sub_data = wdata[[ "no","price","siki_price", "rei_price" ,"menseki" ,"nensu" ,"toho" ] ]
sub_data = sub_data.assign(price=pd.to_numeric( sub_data.price))
print( sub_data.head() )
print(sub_data["price"][: 10])

# 説明変数に "price" 以外を利用
X = sub_data.drop("price", axis=1)
X = X.drop("no", axis=1)

#num_max_x= 10
num_max_x= 1000
X = (X / num_max_x )
print(X.head() )
print(X.shape )
#print( type( X) )
#print(X[: 10 ] )

# 目的変数
num_max_y= num_max_x
Y = sub_data["price"]
Y = Y / num_max_y
print(Y.max() )
print(Y.min() )
#quit()

# 学習データとテストデータに分ける
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.25 ,random_state=0)
x_train =np.array(x_train, dtype = np.float32).reshape(len(x_train), 5)
y_train =np.array(y_train, dtype = np.float32).reshape(len(y_train), 1)
x_test  =np.array(x_test, dtype  = np.float32).reshape(len(x_test), 5 )
y_test =np.array(y_test, dtype   = np.float32).reshape(len(y_test), 1)

print( x_train.shape , y_train.shape  )
print( x_test.shape  , y_test.shape  )
#print(x_train[: 10])
#print(type(x_train ))
#quit()

# train
train_size = x_train.shape[ 0]
batch_size = 100
learning_rate = 0.01
iters_num = 10 * 1000   # 繰り返しの回数を適宜設定する    
#iter_per_epoch = max(train_size / batch_size, 1)
iter_per_epoch = 500
#print(iter_per_epoch )
weight_init_std="relu"
#weight_init_std="sigmoid"
#quit()

# train
global_start_time = time.time()
network = DeepPriceNet(input_size=5
                                , hidden_size_list= [100, 100, 100, 100, 100] , output_size=1, 
                                weight_init_std=weight_init_std, use_batchnorm=True)
optimizer = SGD(lr=learning_rate)
#quit()

bn_train_acc_list = []   
train_loss_list = []     
epoch_cnt = 0

for i in range(iters_num):        
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    y_batch = y_train[batch_mask]
    #
    grads = network.gradient(x_batch, y_batch)
    optimizer.update( network.params, grads)
    #
    if i % iter_per_epoch == 0:
        loss =network.loss(x_train , y_train, train_flg=True)
        train_loss_list.append(loss)
#        print("epoch:" + str(epoch_cnt) + ", time= " + str(time.time() - global_start_time) )
        print("epoch:" + str(epoch_cnt) + ", loss= " + str(loss ) )
        epoch_cnt += 1
# pred
pred =network.predict(x_test )
print(pred[: 10] * num_max_y )
print ('time : ', time.time() - global_start_time)


考察

テストデータの家賃と、予測した家賃

f:id:knaka0209:20181230182009p:plain

ディープラーニングで、kaggle タイタニック問題に挑戦(2) ネットワーク層数の変更

index:

概要

以前の DL版タイタニック問題の関連となり。
ニュラルネットワークのネットワーク層数を増やして、テストしてみました。

環境

python : 3.5.2
numpy
pandas
keras : 2.1.3

テストは、google colab など

学習データ

kaggle の上記ページから、
前回と同様の
学習データ等を、コピーします。


train.csv
test.csv


・目的変数:
 Survived :生存したかどうか。
testデータは、Survivedが、含まれないので注意です。

・説明変数:
年齢、性別など

コード

・ネットワークの層
隠れ層; 5
入力: 1
出力: 1
=> 7層のネットワーク

ニューロンの数
入力: 5(説明変数 の数)
隠れ層:各 100
出力層:1

import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import numpy.random as random
import scipy as sp
from pandas import Series, DataFrame
import pandas as pd
import time

import matplotlib.pyplot as plt
from optimizer import SGD, Adam
from multi_layer_net_extend import MultiLayerNetExtend
from keras.utils import np_utils

#
def get_subData(src ):
    sub=src
    sub["Age"] = src["Age"].fillna( src["Age"].median())
    sub = sub.dropna()
    sub["Embark_flg"] = sub["Embarked"]
    sub["Embark_flg"] = sub["Embark_flg"].map(lambda x: str(x).replace('C', '0') )    
    sub["Embark_flg"] = sub["Embark_flg"].map(lambda x: str(x).replace('Q', '1') )
    sub["Embark_flg"] = sub["Embark_flg"].map(lambda x: str(x).replace('S', '2') )
    sub.groupby("Embark_flg").size()
    # convert, num
    sub = sub.assign( Embark_flg=pd.to_numeric( sub.Embark_flg ))
    sub["Sex_flg"] = sub["Sex"].map(lambda x: 0 if x =='female' else 1)    
    return sub

# 標準化対応、学習。
# 学習データ
train_data = pd.read_csv("train.csv" )
test_data = pd.read_csv("test.csv" )
print( train_data.shape )
#print( train_data.head() )
#
# 前処理 ,欠損データ 中央値で置き換える
train2  = train_data[["PassengerId","Survived","Sex","Age" , "Embarked" ,"SibSp" ,"Parch" ]]
test2   = test_data[ ["PassengerId"           ,"Sex","Age" , "Embarked" ,"SibSp" ,"Parch" ]]
#
age_mid=train2["Age"].median()
#print(age_mid )
print(train2.info() )
print(train2.head(10 ) )
#train2 = train2.dropna()
#train2["Embark_flg"] = train2["Embarked"].map(lambda x: str(x).replace('C', '0') )

train_sub =get_subData(train2 )
test_sub =get_subData(test2 )
print(train_sub.info() )
print(test_sub.info() )
#quit()

# 説明変数と目的変数
x_train= train_sub[["Sex_flg","Age" , "Embark_flg" ,"SibSp" ,"Parch" ]]
y_train= train_sub['Survived']
x_test = test_sub[["Sex_flg","Age" , "Embark_flg" ,"SibSp" ,"Parch" ]]

#conv
num_max_y=10
colmax_x =x_train[ "Age" ].max()
#x_train = x_train / colmax_x
#print(x_train[: 10 ])
#quit()

#print("#check-df")
#col_name="Age"
#print(x_train[ col_name ].max() )
#print(x_train[ col_name ].min() )
#quit()
#np
x_train = np.array(x_train, dtype = np.float32).reshape(len(x_train), 5)
y_train = np.array(y_train, dtype = np.float32).reshape(len(y_train), 1)
#正解ラベルをOne-Hot表現に変換
#y_train = y_train / num_max_y
#x_test  = x_test / num_max_y
y_train=np_utils.to_categorical(y_train, 2)
#
# 学習データとテストデータに分ける
print(x_train.shape, y_train.shape )
print(x_test.shape  )

# train
max_epochs = 50
#train_size = 3000
train_size = x_train.shape[ 0]
batch_size = 100
learning_rate = 0.01
iters_num = 10 * 1000   # 繰り返しの回数を適宜設定する    
#iter_per_epoch = max(train_size / batch_size, 1)
iter_per_epoch = 1000
print(iter_per_epoch )
#weight_init_std="relu"
weight_init_std="sigmoid"
#quit()


# train
global_start_time = time.time()
#
network = MultiLayerNetExtend(input_size=5
                                , hidden_size_list= [100, 100, 100, 100, 100] , output_size=2, 
                                weight_init_std=weight_init_std, use_batchnorm=True)
optimizer = SGD(lr=learning_rate)
#    hidden_size_list=[10, 10, 10, 10, 10 ]
bn_train_acc_list = []    
epoch_cnt = 0

for i in range(iters_num):        
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    y_batch = y_train[batch_mask]
    #
    grads = network.gradient(x_batch, y_batch)
    optimizer.update( network.params, grads)

    if i % iter_per_epoch == 0:
        bn_train_acc = network.accuracy(x_train, y_train)
        bn_train_acc_list.append(bn_train_acc)
        print("epoch:" + str(epoch_cnt) + " | "  + " acc: " + str(bn_train_acc))
        epoch_cnt += 1
# pred
pred =network.predict(x_train)

考察

学習、繰り返し数を増やすと
train acc(正解率) は、 約89%まで上昇しましたが、
テストデータの、精度は前回より、低下しました。。


f:id:knaka0209:20181230132546p:plain

*)改善方法を、検討したいと思います。