pzmm.ImportModel.import_model failed with TypeError after updating from 1.10.0 to 1.10.1

オープン
#184 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
42/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
python, scikit-learn

調査の方向性

リンクされた model_manager_register_sample_sklearn.ipynb を使って失敗を再現し、その後 pzmm/import_model.py と pzmm/write_score_code.py、特に ImportModel.import_model、ScoreCode.write_score_code、ScoreCode._binary_target を読んでください。報告された predict_proba を使用する二値分類の呼び出しが sasctl 1.10.1 上で TypeError なしに正常完了すれば完了です。

索引モデルが issue の本文から書いたものです。

説明

bug

Describe the issue
After updating sasctl to 1.10.1, I experienced TypeError when calling pzmm.ImportModel.import_model with the same code that used to work in 1.10.0.

To Reproduce
Steps or example code to reproduce the issue.

# STEP 5: Import model
pzmm.ScoreCode.score_code = ''
lreg = pzmm.ImportModel.import_model(model_files=model_path, model_prefix=model_prefix, project=project,
                                     input_data=X, predict_method=[model.predict_proba, [float, float]],
                                     score_metrics=score_metrics, overwrite_model=True,
                                     target_values=['0', '1'], model_file_name=model_prefix + ".pickle")

The rest of my sample code can be found here:
https://github.com/pulungw/sascode/blob/main/python/model_manager_register_sample_sklearn.ipynb
Which was based from this article:
https://blogs.sas.com/content/subconsciousmusings/2023/08/11/mlops-for-pirates-and-snakes/

Expected behavior
pzmm.ImportModel.import_model finished execution succesfully like in 1.10.0.

Stack Trace
If you're experiencing an exception, include the full stack trace and error message.

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[12], line 3
      1 # STEP 5: Import model
      2 pzmm.ScoreCode.score_code = ''
----> 3 lreg = pzmm.ImportModel.import_model(model_files=model_path, model_prefix=model_prefix, project=project,
      4                                      input_data=X, predict_method=[model.predict_proba, [float, float]],
      5                                      score_metrics=score_metrics, overwrite_model=True,
      6                                      target_values=['0', '1'], model_file_name=model_prefix + ".pickle")

File ~\AppData\Local\miniconda3\envs\ml\Lib\site-packages\sasctl\pzmm\import_model.py:351, in ImportModel.import_model(cls, model_files, model_prefix, project, input_data, predict_method, score_metrics, pickle_type, project_version, missing_values, overwrite_model, score_cas, mlflow_details, predict_threshold, target_values, overwrite_project_properties, target_index, **kwargs)
    348 # For SAS Viya 4, the score code can be written beforehand and imported with
    349 # all the model files
    350 elif current_session().version_info() == 4:
--> 351     score_code_dict = sc.write_score_code(
    352         model_prefix,
    353         input_data,
    354         predict_method,
    355         score_metrics=score_metrics,
    356         pickle_type=pickle_type,
    357         predict_threshold=predict_threshold,
    358         score_code_path=None if isinstance(model_files, dict) else model_files,
    359         target_values=target_values,
    360         missing_values=missing_values,
    361         score_cas=score_cas,
    362         target_index=target_index,
    363         **kwargs,
    364     )
    365     if score_code_dict:
    366         model_files.update(score_code_dict)

File ~\AppData\Local\miniconda3\envs\ml\Lib\site-packages\sasctl\pzmm\write_score_code.py:280, in ScoreCode.write_score_code(cls, model_prefix, input_data, predict_method, target_variable, target_values, score_metrics, predict_threshold, model, pickle_type, missing_values, score_cas, score_code_path, target_index, **kwargs)
    266         cls.score_code += (
    267             f"\n{'':4}# Check for numpy values and convert to a CAS readable "
    268             f"representation\n"
    269             f"{'':4}if isinstance(prediction, np.ndarray):\n"
    270             f"{'':8}prediction = prediction.tolist()\n\n"
    271         )
    272         """
    273 
    274 # Check for numpy values and conver to a CAS readable representation
   (...)
    278     
    279         """
--> 280         cls._predictions_to_metrics(
    281             score_metrics,
    282             predict_method[1],
    283             target_values=target_values,
    284             predict_threshold=predict_threshold,
    285             target_index=target_index,
    286         )
    288     if missing_values:
    289         cls._impute_missing_values(input_data, missing_values)

File ~\AppData\Local\miniconda3\envs\ml\Lib\site-packages\sasctl\pzmm\write_score_code.py:1138, in ScoreCode._predictions_to_metrics(cls, metrics, predict_returns, target_values, predict_threshold, h2o_model, target_index)
   1136 # Binary classification model
   1137 elif len(target_values) == 2:
-> 1138     cls._binary_target(
   1139         metrics,
   1140         target_values,
   1141         predict_returns,
   1142         predict_threshold,
   1143         target_index,
   1144         h2o_model,
   1145     )
   1146 # Multiclass classification model
   1147 elif len(target_values) > 2:

File ~\AppData\Local\miniconda3\envs\ml\Lib\site-packages\sasctl\pzmm\write_score_code.py:1507, in ScoreCode._binary_target(cls, metrics, target_values, returns, threshold, target_index, h2o_model)
   1498         elif sum(returns) == 0 and len(returns) == 2:
   1499             warn(
   1500                 "Due to the ambiguity of the provided metrics and prediction return"
   1501                 " types, the score code assumes that a classification and the "
   1502                 "target event probability should be returned."
   1503             )
   1504             cls.score_code += (
   1505                 f"{'':4}if input_array.shape[0] == 1:\n"
   1506                 f"{'':8}if prediction[0][{target_index}] > {threshold}:\n"
-> 1507                 f"{'':12}{metrics[0]} = \"{target_values[target_index]}\"\n"
   1508                 f"{'':8}else:\n"
   1509                 f"{'':12}{metrics[0]} = \"{target_values[abs(target_index-1)]}\"\n"
   1510                 f"{'':8}return {metrics[0]}, prediction[0][{target_index}]\n"
   1511                 f"{'':4}else:\n"
   1512                 f"{'':8}df = pd.DataFrame(prediction)\n"
   1513                 f"{'':8}proba = df[{target_index}]\n"
   1514                 f"{'':8}classifications = np.where(df[{target_index}] > {threshold}, '{target_values[target_index]}', '{target_values[abs(target_index-1)]}')\n"
   1515                 f"{'':8}return pd.DataFrame({{'{metrics[0]}': classifications, '{metrics[1]}': proba}})"
   1516             )
   1517             """
   1518 if input_array.shape[0] == 1:
   1519     if prediction[0][1] > .5:
   (...)
   1528     return pd.DataFrame({'Classification': classifications, 'Probability': proba})
   1529                             """
   1530         # TODO: Potentially add threshold
   1531         # Return classification and probability value

TypeError: list indices must be integers or slices, not NoneType

Version
1.10.1

主要言語
Python
スター
52
フォーク
45
PR マージ指標
30日以内にマージされた PR はありません

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

sassoftware/python-sasctl のほかの issue

sassoftware/python-sasctl の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。