解决Snowflake中保存的编码器无法用于推理新数据的问题

解决snowflake中保存的编码器无法用于推理新数据的问题

本文旨在解决在Snowflake中保存OneHotEncoder和OrdinalEncoder后,用于推理新数据时出现`ufunc ‘isnan’ not supported`错误的问题。文章将深入探讨问题原因,并提供一份详细的解决方案,包括正确的编码器调用方式、数据类型转换以及优化的UDF函数实现,确保模型在Snowflake环境中能够稳定可靠地进行预测。

在Snowflake中部署机器学习模型时,将预处理步骤(如One-Hot Encoding和Ordinal Encoding)集成到用户自定义函数(UDF)中是常见的做法。然而,在将训练好的编码器保存到Snowflake并尝试用于新数据推理时,可能会遇到各种问题,其中一个常见的问题是ufunc ‘isnan’ not supported错误。本文将详细介绍如何解决这个问题,并提供一个完整的示例,展示如何在Snowflake中正确地加载和使用编码器进行推理。

问题分析

ufunc ‘isnan’ not supported错误通常表明在尝试对包含非数值数据(例如字符串)的数据执行数值操作。这通常发生在以下情况下:

数据类型不匹配: 输入到编码器的数据类型与编码器训练时使用的数据类型不一致。缺失值处理不当: 编码器在训练时没有正确处理缺失值,导致在推理时遇到未知的缺失值。编码器调用错误: 在UDF中错误地使用了Snowpark API而不是scikit-learn API来转换数据。

解决方案

以下步骤将帮助您解决在Snowflake中保存的编码器无法用于推理新数据的问题:

1. 确保数据类型一致性

在训练和推理阶段,确保输入到编码器的数据类型一致。例如,如果训练数据中的某一列是字符串类型,那么在推理时,该列也必须是字符串类型。可以使用Snowflake的CAST函数或Snowpark的astype方法来转换数据类型。

无涯·问知 无涯·问知

无涯·问知,是一款基于星环大模型底座,结合个人知识库、企业知识库、法律法规、财经等多种知识源的企业级垂直领域问答产品

无涯·问知 40 查看详情 无涯·问知

2. 正确处理缺失值

在训练编码器时,使用handle_unknown和unknown_value参数来处理未知值和缺失值。例如,对于OneHotEncoder,可以将handle_unknown设置为’ignore’来忽略未知类别。对于OrdinalEncoder,可以使用unknown_value参数指定未知值的编码。

from snowflake.ml.modeling.preprocessing import OneHotEncoder,OrdinalEncoderimport numpy as np# OneHotEncoder示例ohe = OneHotEncoder(handle_unknown='ignore', input_cols='CATEGORY', output_cols='ROUTE_OHE')ohe.fit(mock_df)# OrdinalEncoder示例categories = {    "AIRPORT": np.array(['A', 'B', 'C'])}oe = OrdinalEncoder(    handle_unknown='use_encoded_value', unknown_value=-1,    encoded_missing_value=-1, input_cols='AIRPORT',    output_cols='AIRPORT_ENCODE',    categories=categories)oe.fit(mock_ohe)

3. 使用正确的编码器API

在UDF中,由于使用的是Pandas DataFrame,因此需要使用scikit-learn API来转换数据,而不是Snowpark API。将Snowpark的编码器转换为scikit-learn的编码器,再进行数据转换。

# 将Snowpark编码器转换为scikit-learn编码器ohe_obj = ohe.to_sklearn()oe_obj = oe.to_sklearn()# 在UDF中使用scikit-learn API进行转换df_ohe = ohe_obj.transform(df[['ROUTE_CATEGORY_NAME']])

4. 优化UDF函数

为了提高推理性能,可以使用@cachetools.cached装饰器来缓存加载的模型,避免每次调用UDF时都重新加载模型。此外,可以使用向量化UDF,一次性处理整个DataFrame,而不是逐行处理。

import cachetoolsimport pandas as pdfrom snowflake.snowpark.types import PandasDataFrameType,PandasSeriesType,PandasDataFrame,PandasSeriesimport snowflake.snowpark.functions as F@cachetools.cached(cache={})def read_file(filename):    import sys    import os    import joblib    # Get the "path" of where files added through iport are avalible    import_dir = sys._xoptions.get("snowflake_import_directory")    if import_dir:        with open(os.path.join(import_dir, filename), 'rb') as file:            m = joblib.load(file)            return m@F.udf(        name='predict_package_mix_p',session=session,replace=True,        is_permanent=True,stage_location='@AM_TEST_UDFS',        input_type=PandasDataFrameType([IntegerType(),StringType(),StringType(),StringType(),StringType(),StringType(),IntegerType()], list(test_df.schema.names)),        return_type=PandasSeriesType(FloatType()))def predict_package_mix_p(    df:PandasDataFrame) -> PandasSeries:    import pandas as pd    from joblib import load    import sklearn    import xgboost as xgb    import json    import snowflake.ml.modeling    def transform_simple_target_encode_manual(            df,transform_col,transform_df        ):        df = df.merge(transform_df, on=transform_col)        return df    def remove_space(df):        cols = df.columns        space_cols = [x for x in cols if ' ' in x]        for c in space_cols:            new_col = c.replace(" ","_")            df = df.rename(columns={c:new_col})        return df    ohe = read_file('one_hot_encode.pkl')    oe = read_file('ordinal_encode.pkl')    te = pd.read_csv(import_dir + 'target_encoding.csv.gz')    model = read_file('xgb_model.pkl.gz')    print('loaded models')    features = [        "LS1_FLIGHT_ID","DEPARTURE_AIRPORT_CODE","ARRIVAL_AIRPORT_CODE",        "ROUTE_CATEGORY_NAME","DEPARTURE_DATETIME_LOCAL",        "ARRIVAL_DATETIME_LOCAL","CAPACITY"    ]    df.columns = features    print('loaded dataframe')    # transform data for one hot and ordinal encodings    df_ohe = ohe.transform(df[['ROUTE_CATEGORY_NAME']])    encoded_df = pd.DataFrame(df_ohe, columns=ohe.categories_)    encoded_df.columns = encoded_df.columns.get_level_values(0)    encoded_df = encoded_df.add_prefix('ROUTE_NAME_OHE_')    df = pd.concat([df, encoded_df], axis=1)    df['DEPART_CODE_ENCODE'] = oe.transform(df[['DEPARTURE_AIRPORT_CODE']])    print('transformed via one hot and ordinal')    # transform using pre-set target encoding    df_te = transform_simple_target_encode_manual(df,'ARRIVAL_AIRPORT_CODE',te)    df_final = remove_space(df_te)    print('transformed via target encode')    # change date cols to datetime    df_final.loc[:,'DEPARTURE_DATETIME_LOCAL'] = pd.to_datetime(        df_final.loc[:,'DEPARTURE_DATETIME_LOCAL'],format='%Y-%m-%d %H:%M:%S',yearfirst=True    )    df_final['ARRIVAL_DATETIME_LOCAL'] = pd.to_datetime(        df_final['ARRIVAL_DATETIME_LOCAL'],format='%Y-%m-%d %H:%M:%S',yearfirst=True    )    print('transformed dates')    df_final['DEPART_HOUR'] = df_final['DEPARTURE_DATETIME_LOCAL'].dt.hour    # snowpark function goes from 1-7 whereas pandas goes from 0-6    df_final['DEPART_WEEKDAY'] = df_final['DEPARTURE_DATETIME_LOCAL'].dt.day_of_week + 1    df_final['DEPART_MONTHDAY'] = df_final['DEPARTURE_DATETIME_LOCAL'].dt.day    df_final['DEPART_YEARDAY'] = df_final['DEPARTURE_DATETIME_LOCAL'].dt.day_of_year    df_final['DEPART_MONTH'] = df_final['DEPARTURE_DATETIME_LOCAL'].dt.month    df_final['DEPART_YEAR'] = df_final['DEPARTURE_DATETIME_LOCAL'].dt.year    df_final['ARRIVE_HOUR'] = df_final['ARRIVAL_DATETIME_LOCAL'].dt.hour    print('created features')    pm = pd.Series(model.predict(df_final[            ["DEPART_CODE_ENCODE","ROUTE_NAME_OHE_CITY","ROUTE_NAME_OHE_FAR_SUN",            "ROUTE_NAME_OHE_SKI","ROUTE_NAME_OHE_SUN","CAPACITY",            "ARRIVAL_AIRPORT_CODE_ENCODED","DEPART_HOUR",            "DEPART_WEEKDAY","DEPART_MONTHDAY","DEPART_YEARDAY",            "DEPART_MONTH","DEPART_YEAR","ARRIVE_HOUR"]        ]))    return pm

5. 注意事项

列名大小写: Snowflake在存储表时,会将列名转换为大写。因此,在UDF中引用列名时,需要使用大写。模型和编码器版本: 确保在训练和推理阶段使用的模型和编码器版本一致。依赖包: 在Snowflake中注册UDF时,需要添加所有必要的依赖包,例如pandas、joblib、xgboost和scikit-learn。

总结

通过遵循上述步骤,您可以解决在Snowflake中保存的编码器无法用于推理新数据的问题,并构建一个稳定可靠的机器学习推理流程。关键在于确保数据类型一致性,正确处理缺失值,使用正确的编码器API,并优化UDF函数以提高性能。记住,仔细检查代码,并参考Snowflake的官方文档,可以帮助您避免许多常见的错误。

以上就是解决Snowflake中保存的编码器无法用于推理新数据的问题的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/576281.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
韵达快递单号查询官方网站 韵达快递单号查询网页登录
上一篇 2025年11月10日 08:42:34
如何为平面设计师挑选一台电脑?高精度显示的配置要求
下一篇 2025年11月10日 08:42:39

相关推荐

发表回复

登录后才能评论
关注微信