質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.52%

ループ処理における Could not interpret metric function identifier エラーの解決

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,236

mako_H

score 9

機械学習の勉強をしているものです.
python, keras(tensorflow)を使った多クラス分類のプログラムを作成しております.

概ねプログラムが完成し,各種精度を算出したいと考えた際,
https://qiita.com/shiita0903/items/838d50598cc28766f84e
こちらのサイトを見つけ,ソースコードを参考にしました.

これを使い単一のファイルについて各種精度を出せたので,次はディレクトリ内の各々のファイルについて先頭のものから順に読み込み,それぞれのファイルごとの精度を算出しようとしました.
しかし,先頭のファイルの精度を算出し,次のファイルの学習が開始される前に以下のメッセージが表示されプログラムがストップしてしまいます.

ValueError: ('Could not interpret metric function identifier:', 0.XXXX(数値))


なぜ単一のファイルの精度算出ではできfor文ループさせようとするとエラーが出てしまうのか,分かる方がいればご教示頂ければ幸いです.

※ソースコードは一部は省略,修正して載せております.

 該当のソースコード

# -*- coding: utf-8 -*-

import keras.backend as K
import os
import pandas as pd
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.utils import np_utils
from sklearn import preprocessing


# precision, recall, f-measureを定義する
def normalize_y_pred(y_pred):
    return K.one_hot(K.argmax(y_pred), y_pred.shape[-1])


def class_true_positive(class_label, y_true, y_pred):
    y_pred = normalize_y_pred(y_pred)
    return K.cast(
        K.equal(y_true[:, class_label] + y_pred[:, class_label], 2),
        K.floatx())


def true_positive(y_true, y_pred):
    y_pred = normalize_y_pred(y_pred)
    return K.cast(K.equal(y_true + y_pred, 2), K.floatx())


def class_precision(class_label, y_true, y_pred):
    y_pred = normalize_y_pred(y_pred)
    return K.sum(class_true_positive(class_label, y_true, y_pred)) / (
        K.sum(y_pred[:, class_label]) + K.epsilon())


def micro_precision(y_true, y_pred):
    y_pred = normalize_y_pred(y_pred)
    return K.sum(true_positive(y_true, y_pred)) / (K.sum(y_pred) + K.epsilon())


def macro_precision(y_true, y_pred):
    class_count = y_pred.shape[-1]
    return K.sum([class_precision(i, y_true, y_pred) for i in range(class_count)]) \
           / K.cast(class_count, K.floatx())


def class_recall(class_label, y_true, y_pred):
    return K.sum(class_true_positive(class_label, y_true, y_pred)) / (
        K.sum(y_true[:, class_label]) + K.epsilon())


def micro_recall(y_true, y_pred):
    return K.sum(true_positive(y_true, y_pred)) / (K.sum(y_true) + K.epsilon())


def macro_recall(y_true, y_pred):
    class_count = y_pred.shape[-1]
    return K.sum([class_recall(i, y_true, y_pred) for i in range(class_count)]) \
           / K.cast(class_count, K.floatx())


def class_f_measure(class_label, y_true, y_pred):
    precision = class_precision(class_label, y_true, y_pred)
    recall = class_recall(class_label, y_true, y_pred)
    return (2 * precision * recall) / (precision + recall + K.epsilon())


def micro_f_measure(y_true, y_pred):
    precision = micro_precision(y_true, y_pred)
    recall = micro_recall(y_true, y_pred)
    return (2 * precision * recall) / (precision + recall + K.epsilon())


def macro_f_measure(y_true, y_pred):
    precision = macro_precision(y_true, y_pred)
    recall = macro_recall(y_true, y_pred)
    return (2 * precision * recall) / (precision + recall + K.epsilon())


def build_multilayer_perceptron():
    """多層パーセプトロンモデルを構築"""
    model = Sequential()
    model.add(Dense(16, input_shape=(12, )))
    model.add(Activation('relu'))
    model.add(Dense(2))
    model.add(Activation('softmax'))
    return model


if __name__ == "__main__":
    with open("result.csv", "w") as f:
        print("date,accuracy,precision,recall,f_measure", file=f)

    for i in range(1, 32):
        # ファイルが存在すれば読み込み,以下を実行する
        if (os.path.exists(
                os.path.join("data", "hoge", "20XX", "01",
                             "20XX010" + str(i) + ".txt"))
                or os.path.exists(
                    os.path.join("data", "hoge", "20XX", "01",
                                 "20XX01" + str(i) + ".txt"))):
            if i < 10:
                dataset = pd.read_csv(
                    os.path.join("data", "hoge", "20XX", "01",
                                 "20XX010" + str(i) + ".txt"),
                    delim_whitespace=True)
            else:
                dataset = pd.read_csv(
                    os.path.join("data", "hoge", "20XX", "01",
                                 "20XX01" + str(i) + ".txt"),
                    delim_whitespace=True)

            # 説明変数,ターゲット変数を定義
            X = dataset.iloc[:, [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
            Y = dataset.iloc[:, 17]

            # データの標準化
            X = preprocessing.scale(X)

            # ラベルをone-hot-encoding形式に変換
            # 0 => [1, 0, 0]
            # 1 => [0, 1, 0]
            # 2 => [0, 0, 1]
            Y = np_utils.to_categorical(Y)

            # 訓練データとテストデータに分割
            train_X, test_X, train_Y, test_Y = train_test_split(
                X, Y, train_size=0.8, test_size=0.2)

            # print(macro_precision)
            # print(macro_recall)
            # print(macro_f_measure)

            # モデル構築
            model = build_multilayer_perceptron()
            model.compile(
                optimizer='adam',
                loss='categorical_crossentropy',
                metrics=[
                    'accuracy', macro_precision, macro_recall, macro_f_measure
                ])

            # モデル訓練
            model.fit(train_X, train_Y, epochs=1, batch_size=100, verbose=1)

            # モデル評価
            loss, accuracy, macro_precision, macro_recall, macro_f_measure = model.evaluate(
                test_X, test_Y, verbose=0)

            # print(macro_precision)
            # print(macro_recall)
            # print(macro_f_measure)

            # 学習,評価結果を保存
            with open("result.csv", "a") as f:
                print(
                    "{0},{1},{2},{3},{4}".format(
                        str(i), accuracy, macro_precision, macro_recall,
                        macro_f_measure),
                    file=f)

エラー文が出て止まった際の箇所

metrics=[
    'accuracy', macro_precision, macro_recall,
    macro_f_measure
])

 補足情報(FW/ツールのバージョンなど)

・Python 3.6.5
・Keras 2.2.4
・Tensorflow 1.11.0

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

エラーを見たところ

'Could not interpret metric function identifier:', 0.XXXX(数値)

とのことなので、'macro_precision', 'macro_recall' 'macro_f_measure' という関数名と同じ名前の変数名を定義してしまっていたりしないですか?

print(macro_precision)
print(macro_recall)
print(macro_f_measure)

として確認してみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/16 19:30

    >モデル訓練の処理後と書いていますが、compile()の段階、つまりモデル訓練の前にエラーになったのですよね?
    そうです.print文でデバッグしたところ,i=1のときのモデル訓練(評価)後それぞれの変数の値がアドレスから数値になり,i=2のときモデル訓練の前にエラーで止まってしまっております.
    >原因ですが、提示されてるのがコードの一部だけなのでわかりません。
    >関数名と同じ名前の変数を使っていないか確認してください
    全文を載せました.また,同じ名前の変数は,#モデル構築,#モデル評価,#学習,評価結果を保存,の箇所でしか使っておりません.

    キャンセル

  • 2018/11/16 19:37

    > loss, accuracy, macro_precision, macro_recall, macro_f_measure = model.evaluate(test_X, test_Y, verbose=0)

    回答の通り、ここで「関数名と同じ名前の変数」を定義してしまっていますね。関数名と重複する名前を変数名に使わないようにしてください。
    つまり、解決策としては、ここの evaluate() の返り値を代入している変数名を変えてください。

    キャンセル

  • 2018/11/17 09:42

    そちらで定義しまっているのを失念しておりました.よく考えればそうですよね.恥ずかしい...
    無事,解決いたしました.何度も解答してくださり,ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る