趋近智
机器学习 (machine learning)工作流程经常需要重复应用操作、根据运行时条件定制行为,或构建封装特定逻辑的可重用组件。高阶函数和闭包是强大的Python特性,它们使这些目标得以优雅地实现,从而使机器学习管线中的代码更加灵活和易于维护。
如果一个函数满足以下一个或两个条件,它就被称为高阶函数 (HOF):
这种将函数视为一等公民,像传递其他任何对象(整数、字符串、列表)一样传递它们的能力,为抽象提供了重要的途径。
考虑一个常见任务:对数据集应用不同的预处理步骤。我们可以使用一个高阶函数,而不是编写大量重复迭代逻辑的独立函数:
import pandas as pd
import numpy as np
def apply_transformation(data: pd.DataFrame, column: str, transformation_func):
"""将给定的转换函数应用于特定列。"""
# 基本验证(生产环境中需要更多检查)
if column not in data.columns:
raise ValueError(f"Column '{column}' not found in DataFrame.")
# 创建副本以避免直接修改原始DataFrame
data_transformed = data.copy()
data_transformed[column] = data[column].apply(transformation_func)
return data_transformed
# 示例转换函数
def log_transform(x):
# 如果需要,添加一个小常量来处理零值或负值
return np.log1p(x)
def standardize(x, mean, std):
# 注意:此简单版本需要均值/标准差。闭包在此处会有所帮助。
if std == 0:
return x - mean
return (x - mean) / std
# --- 使用高阶函数 ---
# 示例数据
df = pd.DataFrame({'feature1': [1, 10, 100, 1000, 0], 'feature2': [5, 5, 5, 5, 5]})
# 使用高阶函数应用对数转换
df_log = apply_transformation(df, 'feature1', log_transform)
print("对数转换后的feature1:\n", df_log)
# 问题:如何在apply_transformation中将均值/标准差传递给standardize?
# 我们可以修改apply_transformation,但闭包提供了更简洁的方法。
apply_transformation 函数是一个高阶函数,因为它接受 transformation_func 作为参数。它将对列应用某个函数的过程抽象化,使管道组件更具通用性。
Python的内置函数,如 map 和 filter,也是高阶函数的例子。functools.partial 是另一个有用的高阶函数,它创建一个新函数,并预先填充原始函数的某些参数。
现在,我们来解决 standardize 函数对 mean 和 std 的需求。我们希望 apply_transformation 只要求一个接受单个参数 (parameter)(列数据)的函数。这正是闭包派上用场的地方。
闭包是一个函数对象,它能记住其封闭词法作用域中的值,即使程序流不再处于该作用域中。简而言之,在外部函数内部定义的内部函数可以在外部函数执行完毕后很长时间内访问并使用外部函数的变量。
我们可以创建一个“工厂”函数,使用闭包生成特定的转换函数:
import pandas as pd
import numpy as np
def create_standardizer(mean, std):
"""返回一个配置了特定均值和标准差的标准化函数。"""
def standardizer_func(x):
"""此内部函数是一个闭包。它“记住”了均值和标准差。"""
if std == 0:
return x - mean # 避免除以零
return (x - mean) / std
return standardizer_func # 返回配置好的内部函数
# --- 使用闭包工厂 ---
# 示例数据(与之前相同)
df = pd.DataFrame({'feature1': [1, 10, 100, 1000, 0], 'feature2': [5, 5, 5, 5, 5]})
# 计算特征的均值和标准差(实践中应在训练数据上拟合)
f1_mean = df['feature1'].mean()
f1_std = df['feature1'].std()
# 使用工厂为feature1创建一个特定的标准化器
standardize_feature1 = create_standardizer(f1_mean, f1_std)
# 现在,standardize_feature1是一个只接受一个参数(x)的函数
# 并且可以直接与apply_transformation一起使用
# 重新使用之前定义的apply_transformation高阶函数
df_standardized = apply_transformation(df, 'feature1', standardize_feature1)
print("\n使用闭包对feature1进行标准化:\n", df_standardized)
# 你可以轻松创建其他标准化器
f2_mean = df['feature2'].mean()
f2_std = df['feature2'].std()
standardize_feature2 = create_standardizer(f2_mean, f2_std)
df_std_f2 = apply_transformation(df, 'feature2', standardize_feature2)
print("\n使用闭包对feature2进行标准化:\n", df_std_f2)
闭包 (
standardizer_func) 即使在其封闭函数 (create_standardizer) 返回后,仍能访问该函数的变量 (mean,std)。
在此示例中,create_standardizer 是一个高阶函数,因为它返回一个函数 (standardizer_func)。返回的函数 standardizer_func 是一个闭包,因为它封装了其创建环境中的 mean 和 std 值。这种模式使我们能够即时创建专用函数,根据机器学习 (machine learning)工作流程中计算出的特定参数(例如从训练集得出的统计数据)进行定制。
在使用高阶函数和闭包构建机器学习管线时,它们提供了以下几个优势:
apply_transformation 这样的通用高阶函数可以用于各种操作,减少代码重复。使用闭包的函数工厂能够生成可重用、已配置的函数。考虑构建一个用于模型评估的自定义评分函数,您希望对某些类型的错误施加更重的惩罚。一个高阶函数可以接受基本度量函数(例如,均方误差)和一个惩罚函数,然后返回一个组合评分函数。闭包可以在惩罚函数内部使用,以记住特定的惩罚权重。
通过将高阶函数和闭包融入您的工具集,您将获得强大的技术,用于为高级Python机器学习管线构建更抽象、可配置且易于维护的组件。它们鼓励编写将执行什么操作与在更广阔的工作流程中如何应用操作分离的代码。
这部分内容有帮助吗?
functools - Higher-order functions and operations on callable objects, Python Software Foundation, 2023 (Python Software Foundation) - Python functools 模块的官方文档,提供了处理高阶函数的工具,包括用于函数定制的 partial。© 2026 ApX Machine Learning用心打造