Azure Machine Learning の Jupyter Notebook 対応 ( Variable Selection 編 )


Microsoft Japan Data Platform Tech Sales Team

森本 信次

 

Azure ML でも 図1のように、3つの Feature Selecction ( 特徴選択 ) が使えるのですが、この 「Feature Elimination」については 今のところ対応していませんので、今回の投稿では Juypter Notebook および Python のライブラリを使ってこの特徴選択の手法を試してみいたと思います。

ウィキペディア によると、特徴選択(とくちょうせんたく、英: feature selection)とは、機械学習と統計学の用語であり、頑健な学習モデルの構築のため、特徴集合のうち意味のある部分集合だけを選択する手法のことを指します。詳しくはこちらをご覧ください。

1.  Filter Based Feature Selection

2. Fisher Linear Discriminant Analysis

3. Permulation Feature Importance

AzureMLFS

図1. Azure Machine Learning Studio の Feature Selection Items

 

Read Data ( データの読み込み )

このサンプルではボストンの住宅に関するデータセットを使用します。データセットには 506 件のデータが含まれ、13種類の説明変数  ( 部屋の数、築年数、町の犯罪率 など ) があります。データセットの詳しい説明はこちらをご覧ください。

from sklearn.datasets import load_boston
boston = load_boston()
X = boston.data
y = boston.target
feature_names = boston.feature_names
print(X.shape)
print(y.shape)
print(feature_names)

 

上記のコードの実行結果です。

(506, 13)
(506,)
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT']

 

Recursive Feature Elimination ( 再帰的特徴選択 )

Python の sklearn パッケージ にはいくつかの 特徴選択のメソッドが含まれています。このサンプルではこのパッケージの 「Recursive Feature Elimination」 メソッドを使うことにします。このプロセスではすべての変数に対して重みづけを行い、重みが小さいものから取り除いていきます。残りの変数はモデルの再フィットおよびこのプロセスを繰り返すのに使用します。skleann 詳細についてはこちらをご覧ください。

まず必要となるパッケージをインポートするところから始めましょう。

%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn import preprocessing
from sklearn.feature_selection import RFECV

 

以下のコードでは最初に特徴をスケールさせて、「Recursive Featrue Elimination」 メソッドにより どの特徴を使用するかを選択しています。

# initiate the linear model
lm = LinearRegression()

# scale the features
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled_minmax = min_max_scaler.fit_transform(X)
x_scaled_minmax_df = pd.DataFrame(x_scaled_minmax, columns = feature_names)

# recursive feature elimination with cross validation, using r-squared as metric
rfecv = RFECV(estimator=lm, step=1, cv=5, scoring='r2')
rfecv.fit(x_scaled_minmax_df, y)

# print the optimal number of feature (最適な特徴の数)
print("Optimal number of features : %d" % rfecv.n_features_)

# save the selected features (選択された特徴)
feature_cols_selected = list(np.array(feature_names)[rfecv.support_])
print("Features selected: " + str(feature_cols_selected))

# plot number of features VS. cross-validation scores
plt.figure()
plt.xlabel("Number of features selected")
plt.ylabel("R-squared")
plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_)
plt.show()

 

OptimalFeatureSelected

 

このように含めるべき特徴 ( 今回のケースでは 6 種類 )を特定できたので、次にモデルのフィッティングを行います。上記の RFE ( Recursive Feature Elimination )ステップではスケールさせた特徴を使いましたが、今回のモデルのフィッティングはオリジナルの値を使うことにします。この方法では予測を行うときにデータを変換する必要がありません。

#%% fit model with selected features
X_new = X[:,rfecv.support_]
lm2 = LinearRegression()
lm2.fit(X_new, y)

# print the R-squared
print("The R-squared value is: {0:0.4f} \n".format(lm2.score(X_new, y)))
# save intercept and coefficients
param_df = pd.DataFrame({"Features": ['intercept'] + feature_cols_selected, "Coef": [lm2.intercept_] + list(lm2.coef_)})
cols = param_df.columns.tolist()
cols = cols[-1:]+cols[:-1]
param_df = param_df[cols]
print(param_df)

 

次に予測を行うためモデルを使ってみましょう、通常は適切なデータセットに基づいて予測を行うべきですが、今回は解説を目的としているため簡易的なデータセットを使用しています。

# assign test data
newX = X_new
newY = y

# make predictions
predicted = lm2.predict(newX)
predictedDf = pd.DataFrame({"predicted": predicted})

# dataframe for X
newXDf = pd.DataFrame(newX)
newXDf.columns = feature_cols_selected
# dataframe for y
newYDf = pd.DataFrame(newY)
newYDf.columns = ['MEDV']
# join X, y and prediction
mydata_with_pd = newXDf.join(newYDf).join(predictedDf)
mydata_with_pd.head()

DataSetForTraining

 

# check performance metrics
import numpy as np
obs = mydata_with_pd.MEDV
pred = mydata_with_pd.predicted

mae = np.mean(abs(pred-obs))
rmse = np.sqrt(np.mean((pred-obs)**2))
rae = np.mean(abs(pred-obs))/np.mean(abs(obs-np.mean(obs)))
rse = np.mean((pred-obs)**2)/np.mean((obs-np.mean(obs))**2)

print("Mean Absolute Error: {0:0.6f}".format(mae))
print("Root Mean Squared Error: {0:0.6f}".format(rmse))
print("Relative Absolute Error: {0:0.6f}".format(rae))
print("Relative Squared Error: {0:0.6f}".format(rse))

Mean Absolute Error: 3.467774
Root Mean Squared Error: 4.936601
Relative Absolute Error: 0.521689
Relative Squared Error: 0.288678

 

Web サービスのセットアップ

モデルの開発後には、そのモデルを Web サービスとしてデプロイすることで、他からそのモデルを使用できるようになります。以下では Webサービスのデプロイをサポートする 「azureml」 パッケージを Notebook 環境へインポートして、「demoserviceVarSel」 という名前の Web サービスをセットアップしています。

# extract workspace info
from azureml import Workspace
ws = Workspace()
workdspace_id = ws.workspace_id
authorization_token = ws.authorization_token

# set up web service
from azureml import services
@services.publish(workdspace_id, authorization_token)
@services.types(crim = float, nox=float, rm=float, dis=float, ptratio=float, lstat=float)
@services.returns(float)
def demoserviceVarSel(crim, nox, rm, dis, ptratio, lstat):
     feature_vector = [crim, nox, rm, dis, ptratio,  lstat]
     return lm2.predict(feature_vector)

 

service_url = demoserviceVarSel.service.url
api_key = demoserviceVarSel.service.api_key
help_url = demoserviceVarSel.service.help_url
service_id = demoserviceVarSel.service.service_id

 

Webサービスの使用

以下のコードの目的は Web サービスがデプロイされて使用可能になるまで数秒待つことです。

# wait
import time
time.sleep(10)

 

以下のコードでは Web サービスを使用するためのものです。

import urllib2
# If you are using Python 3+, import urllib instead of urllib2

import json

data =  {

        "Inputs": {

                "input1":
                {
                    "ColumnNames": ["crim", "lstat", "nox", "rm", "ptratio", "dis"],
                    "Values": [ [ "0.00632", "4.98", "0.538", "6.575", "15.3", "4.0900" ],
                               [ "0.02731", "9.14", "0.469", "6.421", "17.8", "4.9671" ], ]
                },        },
            "GlobalParameters": {
}
    }

body = str.encode(json.dumps(data))

url = service_url
api_key = api_key # Replace this with the API key for the web service

headers = {'Content-Type':'application/json', 'Authorization':('Bearer '+ api_key)}

req = urllib2.Request(url, body, headers)

try:
    response = urllib2.urlopen(req)

    # If you are using Python 3+, replace urllib2 with urllib.request in the above code:
    # req = urllib.request.Request(url, body, headers)
    # response = urllib.request.urlopen(req)

    result = response.read()
    print(result)
except urllib2.HTTPError, error:
    print("The request failed with status code: " + str(error.code))

    # Print the headers - they include the requert ID and the timestamp, which are useful for debugging the failure
    print(error.info())

    print(json.loads(error.read())) 

 

予測結果です。

{"Results":{"output1":{"type":"table","value":{"Values":[["31.3651262005007"],["26.018746711909"]]}},"output2":{"type":"table","value":{"Values":[["data:text/plain,Execution OK\r\n",null]]}}}}

 

上記の Web サービスを使用するコードは help_url に基づいており、今回使用した言語 Python 以外にも C# や R を使った場合の Web サービス使用のサンプルコードを確認することができます。help_url をブラウザーから開き “Python” タブ の “Sample Code” にサンプルコードが掲載されています。

SampleCode

 

まとめ

いかがでしたでしょうか ?  ここまでで Jupyter Notebook を使用した 特徴選択の手法の一つである 「Featuer Elimination」 を Azure ML の Juypter Notebook 環境で使う場合の一連の流れを見ていただきました。Azure Machine Learning Studio には他にも 解説付きのNotebookが提供されいますので、是非お試しいただければと思います。

Comments (0)

Skip to main content