TensorFlowを使用した機械学習予測とTripAdvisorデータ

TensorFlowを使用した機械学習予測とTripAdvisorデータ

  • 人工知能(AI)
6分で読めます 更新日 May 21, 2018

ポイント: TensorFlowを活用して、ニューラルネットワークを構築し、CSVデータからデータセットを作成してTripAdvisorホテル評価を予測し、モデルを訓練して1から5までの評価を分類します。手法にはデータの解析、テンソルの作成、DNNClassifierの利用が含まれます。

  • コード例はデータ前処理とモデル訓練を示します。
  • TensorFlowの機能を統合することで予測精度が向上します。

ここではTripadvisorデータの分析の最後の部分を示します。パート1はこちらです。これを理解するには、PythonとNumpy配列、そしてTensorFlowとニューラルネットワークの基本を知っておく必要があります。知らない場合は、TensorFlowの紹介をこちらで読むことができます。

この例のコードはこちらで、入力データはこちらです。Tensorflowを使用してニューラルネットワークを作成します。tf.estimator.DNNClassifierを使用します。(DNNは深層ニューラルネットワークを意味し、入力層と出力層の間に隠れ層があることを示します。)

以下では、コードの各セクションについて説明します。

parse_line

feature_namesは、特徴列に割り当てた名前です。

FIELD_DEFAULTSは20の整数の配列です。これは、TensorFlowに対して入力が整数であり、20の特徴があることを示します。1.0を使用していた場合、それらは浮動小数点数として宣言されます。

parse_line

    import tensorflow as tf
import numpy as np
feature_names = ['Usercountry', 'Nrreviews','Nrhotelreviews','Helpfulvotes','Periodofstay',
'Travelertype','Pool','Gym','Tenniscourt','Spa','Casino',
'Freeinternet','Hotelname','Hotelstars','Nrrooms','Usercontinent',
'Memberyears','Reviewmonth','Reviewweekday']
FIELD_DEFAULTS = [[0], [0], [0], [0], [0],
[0], [0], [0], [0], [0],
[0], [0], [0], [0], [0],
[0], [0], [0], [0], [0]]

DNNClassifier.trainには、特徴とラベルを返すinput_fnが必要です。引数を持って呼び出すべきではないので、以下のlambdaを使用して、それを反復的に呼び出し、読み取るテキストファイルの名前をパラメータとして渡します。

TensorFlowが提供する例の一つ、すなわちIrisフラワーデータを読み取るようなhellowordタイプのものを使用することはできません。自分たちのデータを作成し、それを.csvファイルに入れました。したがって、自分のパーサーが必要です。この場合、tf.data.TextLineDatasetメソッドを使用してcsvテキストファイルから読み取り、これをパーサーに供給します。それによって、これらの行を読み取り、特徴とラベルを辞書とテンソルのペアとして返します。

del parsed_line[4]では、入力から5番目のテンソルを削除しました。これはTripadvisorのスコアです。なぜなら、それはラベル(すなわち出力)であり、特徴(入力)ではないからです。

tf.decode_csv(line, FIELD_DEFAULTS)は、.csvファイルから読み取った各アイテムのテンソルを作成します。

テンソルは値を持っていないため、見ることはできません。そして、テンソルセッションを実行するまで値を持っていません。しかし、これらの値を確認するにはtp.Print()を使用できます。また、デバッグ目的で解析関数をテストするには、以下のようにすることもできます。

    import pandas as pd
df = pd.read_csv("/home/walker/TripAdvisor.csv")
ds = df.map(parse_line)

説明を続けると、dict(zip(feature_names, features))は特徴テンソルと特徴名から辞書を作成します。ラベルはlabel = parsed_line[4]として、parsed_lineの5番目のアイテムから割り当てます。

csv_input

    def parse_line(line):
parsed_line = tf.decode_csv(line, FIELD_DEFAULTS)
tf.Print(input_=parsed_line , data=[parsed_line ], message="parsed_line ")
tf.Print(input_=parsed_line[4], data=[parsed_line[4]], message="score")
label = parsed_line[4]
del parsed_line[4]
features = parsed_line
d = dict(zip(feature_names, features))
return d, label

データセットはTensorflowのデータセットであり、単純なPythonオブジェクトではありません。tf.data.TextLineDataset(csv_path)を使用して.csvテキストファイルからデータセットを作成した後、dataset.map()メソッドでparse_lineを呼び出します。

    def csv_input_fn(csv_path, batch_size):
dataset = tf.data.TextLineDataset(csv_path)
dataset = dataset.map(parse_line)
dataset = dataset.shuffle(1000).repeat().batch(batch_size)
return dataset

テンソルを作成

ここでは、カテゴリカルではなく連続的な数としてテンソルを作成します。これは正しいですが改善の余地があります。以下に注意してください。

    Note: User country, is a set of discrete values.  So we could have used, for example, Usercountry = tf.feature_column.indicator_column(tf.feature_column. categorical_column_with_identity("Usercountry",47))
since there are 47 countries in our dataset.  You can experiment with that and see if you can make that change. I got errors trying to get that to work since tf.decode_csv() appeared to be reading the wrong column in certain cases this given values that were, for example, not one of the 47 countries.  So there must be a few rows in the input data that has a different number of commas than the others.  You can experiment with that.

最後にfeature_columnsは、作成したテンソルの配列です。

    Usercountry = tf.feature_column.numeric_column("Usercountry")
Nrreviews = tf.feature_column.numeric_column("Nrreviews")
Nrhotelreviews = tf.feature_column.numeric_column("Nrhotelreviews")
Helpfulvotes = tf.feature_column.numeric_column("Helpfulvotes")
Periodofstay = tf.feature_column.numeric_column("Periodofstay")
Travelertype = tf.feature_column.numeric_column("Travelertype")
Pool = tf.feature_column.numeric_column("Pool")
Gym = tf.feature_column.numeric_column("Gym")
Tenniscourt = tf.feature_column.numeric_column("Tenniscourt")
Spa = tf.feature_column.numeric_column("Spa")
Casino = tf.feature_column.numeric_column("Casino")
Freeinternet = tf.feature_column.numeric_column("Freeinternet")
Hotelname = tf.feature_column.numeric_column("Hotelname")
Hotelstars = tf.feature_column.numeric_column("Hotelstars")
Nrrooms = tf.feature_column.numeric_column("Nrrooms")
Usercontinent = tf.feature_column.numeric_column("Usercontinent")
Memberyears = tf.feature_column.numeric_column("Memberyears")
Reviewmonth = tf.feature_column.numeric_column("Reviewmonth")
Reviewweekday = tf.feature_column.numeric_column("Reviewweekday")
feature_columns = [Usercountry, Nrreviews,Nrhotelreviews,Helpfulvotes,Periodofstay,
Travelertype,Pool,Gym,Tenniscourt,Spa,Casino,Freeinternet,Hotelname,
Hotelstars,Nrrooms,Usercontinent,Memberyears,Reviewmonth,
Reviewweekday]

分類器を作成

これでモデルを訓練します。hidden_units [10,10]は、深層ニューラルネットワークの最初の隠れ層に10ノードがあり、2番目にも10ノードがあることを意味します。model_dirは、訓練したモデルを保存する一時フォルダーです。ホテルのスコアは1から5の範囲なので、n_classesは6であり、バケットの数より大きくなければなりません。

モデルを訓練

    classifier=tf.estimator.DNNClassifier(
feature_columns=feature_columns,
hidden_units=[10, 10],
n_classes=6,
model_dir="/tmp")
batch_size = 100

モデルを訓練します。ドキュメントによれば、「Estimatorは、引数を取らないinput_fnを期待します。この制約を回避するために、引数をキャプチャし、期待されるインターフェースを提供するためにlambdaを使用します。」

    classifier.train(
steps=100,
input_fn=lambda : csv_input_fn("/home/walker/tripAdvisorFL.csv", batch_size))

予測を行う

訓練したモデルで予測を行います。実際には、評価ステップも実行する必要があります。GitHubのコードではそれも書いていますが、評価ステップを終了しませんでした。したがって、ここで整理するべき未解決の問題が残ります。

テスト用のデータが必要です。トレーニングセットの入力から最初の行を取得し、ここに入力します。レビュアーはホテルに5点を付けました。したがって、私たちの期待される結果は5です。ニューラルネットワークは、期待される結果が5である確率を示します。classifier.predict()メソッドは、実行するように指示した入力関数を実行します。この場合は、predict_input_fn().それは特徴を辞書として返します。評価を実行していた場合は、特徴とラベルの両方が必要です。

    features = {'Usercountry': np.array([233]), 'Nrreviews': np.array([11]),'Nrhotelreviews': np.array([4]),'Helpfulvotes': np.array([13]),'Periodofstay': np.array([582]),'Travelertype': np.array([715]),'Pool' : np.array([0]),'Gym' : np.array([1]),'Tenniscourt' : np.array([0]),'Spa' : np.array([0]),'Casino' : np.array([0]),'Freeinternet' : np.array([1]),'Hotelname' : np.array([3367]),'Hotelstars' : np.array([3]),'Nrrooms' : np.array([3773]),'Usercontinent' : np.array([1245]),'Memberyears' : np.array([9]),'Reviewmonth' : np.array([730]),'Reviewweekday' : np.array([852])}
def predict_input_fn():
return features
expected = [5]
prediction = classifier.predict(input_fn=predict_input_fn)
for pred_dict, expec in zip(prediction, expected):
class_id = pred_dict['class_ids'][0]
probability = pred_dict['probabilities'][class_id]
print ('class_ids=', class_id, ' probabilities=',  probability)

結果を印刷します。この例における5の確率は38%です。近くで、例えば90%に近い結果が得られることを期待します。これは外れ値かもしれません。モデルを評価するまではわかりません。

明らかに、モデルを見直して、追加データで再試行する必要があります。ホテルのスコアは、確かに私たちが与えたTripadvisorデータと相関があると思われます。しかし、ここでの焦点は、モデルを機能させることだけです。今、微調整を行い、他のMLモデルがより適切かどうかを確認する必要があります。

    class_ids= 5  probabilities= 0.38341486

補遺

上記のように離散値列を作成するためにこれらを試すことができます:

    Usercountry = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Usercountry",47))
Nrreviews = tf.feature_column.numeric_column("Nrreviews")
Nrhotelreviews = tf.feature_column.numeric_column("Nrhotelreviews")
Helpfulvotes = tf.feature_column.numeric_column("Helpfulvotes")
Periodofstay = tf.feature_column.numeric_column("Periodofstay")
Travelertype = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Travelertype",5))
Pool = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Pool",2))
Gym = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Gym",2))
Tenniscourt = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Tenniscourt",2))
Spa = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Spa",2))
Casino = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Casino",2))
Freeinternet = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Freeinternet",2))
Hotelname = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Hotelname",22))
Hotelstars = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Hotelstars",5))
Nrrooms = tf.feature_column.numeric_column("Nrrooms")
Usercontinent = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Usercontinent",6))
Memberyears = tf.feature_column.numeric_column("Memberyears")
Reviewmonth = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Reviewmonth",12))
Reviewweekday = tf.feature_column.indicator_column(tf.feature_column.
categorical_column_with_identity("Reviewweekday",7))

これらの投稿は私自身のものであり、必ずしもBMCの立場、戦略、または意見を示すものではありません。

人工知能(AI)の関連記事

BMCからのさらなる情報に興味がありますか?

ザ・ブリーフは、メインフレームとエンタープライズオーケストレーションに関する月刊メールです:研究、顧客ストーリー、製品ニュース、イベント。

このオファーに登録することで、あなたはBMCのプライバシーポリシーを読み、同意したことを確認します。

ザ・ブリーフに登録しました

ザ・ブリーフは、メインフレームとエンタープライズオーケストレーション—BMC AMIおよびControl-M—に関するアナリストの研究、顧客の展開、両者にわたるイベントを網羅しています。