You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Julia中高效生成多项式组合特征矩阵的方法求助

高效生成多项式特征矩阵的Julia方案

在Julia里想要实现类似Python scikit-learn PolynomialFeatures的高效多项式特征生成,其实有不少现成的优质工具,也可以对你的手动实现做针对性优化,下面分两种情况给你说明:

一、用现成库函数(优先推荐)

自己手动写循环很容易因为内存分配和低效操作拖慢速度,Julia生态里已经有成熟的工具可以直接用,性能和易用性都有保障:

1. MLJModels.jl 的 PolynomialFeatures

MLJModels是Julia机器学习生态里的工具集,它的PolynomialFeatures和你熟悉的scikit-learn版本功能几乎一致,而且经过优化,处理大数据量时速度会快很多。

举个实际使用的例子:

using MLJModels, DataFrames

# 构造你的输入数据框
df = DataFrame(x = [1, 2], y = [3, 4])

# 初始化转换器:设置阶数为2,不包含偏置项(对应Python里的include_bias=False)
poly_transformer = PolynomialFeatures(degree=2, include_bias=false)

# 拟合转换器并转换数据
# 可以直接传入DataFrame或者矩阵,这里用矩阵演示
X = Matrix(df)
X_poly = transform(fit!(machine(poly_transformer, X)), X)

# 如果需要获取特征名称,直接调用feature_names方法即可
feature_names(poly_transformer)

运行后得到的X_poly就是你需要的特征矩阵,特征名称也会自动生成(比如x, y, x², x*y, y²),完全符合你的需求。

2. StatsModels.jl 的公式语法

如果你习惯用公式来定义特征,StatsModels的@formula可以非常灵活地生成多项式特征,尤其适合和后续的建模流程结合:

using StatsModels, DataFrames

df = DataFrame(x = [1, 2], y = [3, 4])

# 用公式定义二阶多项式特征,包含原始特征、平方项和交叉项
f = @formula(0 ~ x + y + x^2 + y^2 + x&y)
# 生成特征矩阵,去掉第一列的截距项(对应不包含偏置)
X_poly = modelmatrix(f, df)[:, 2:end]

这种方式不需要额外的转换器,直接通过公式就能生成想要的特征,用起来很顺手。

二、优化你的手动实现

如果因为某些特殊需求必须自己写函数,你的原函数慢的核心问题是循环里反复用hcat——每次hcat都会重新分配内存,数据量大的时候开销会爆炸。可以通过以下方式优化:

1. 预分配内存+广播操作

先算出最终特征矩阵的大小,一次性分配好内存,再用广播填充数据,避免反复的内存分配:

function poly_opt(data, vars, deg)
    mat = Matrix(data[:, vars])
    n, s = size(mat)
    
    if deg == 1
        return mat, vars
    elseif deg == 2
        # 计算总特征数:原始s个 + s*(s+1)/2个二阶项(平方+交叉)
        total_features = s + s*(s+1)÷2
        # 预分配结果矩阵,和原始矩阵类型一致
        p = similar(mat, n, total_features)
        # 先填充原始特征
        p[:, 1:s] = mat
        
        varnm = String[]
        append!(varnm, string.(vars))
        
        idx = s + 1
        for i in 1:s
            for j in i:s
                # 用广播计算列,比手动循环快很多
                p[:, idx] = mat[:, i] .* mat[:, j]
                # 生成特征名称
                if i == j
                    push!(varnm, "$(vars[i])²")
                else
                    push!(varnm, "$(vars[i])*$(vars[j])")
                end
                idx += 1
            end
        end
        return p, varnm
    else
        error("目前仅实现了1阶和2阶的情况,如需更高阶可以扩展")
    end
end

这个版本去掉了所有不必要的内存分配,用Julia擅长的广播操作替代了低效循环,性能会比你的原函数提升很多。

2. 通用高阶版本(支持任意阶数)

如果需要支持更高阶的多项式,可以用迭代器生成所有指数组合,再批量计算:

using Iterators

function poly_general(data, vars, deg)
    mat = Matrix(data[:, vars])
    n, s = size(mat)
    
    # 生成所有满足指数和≥1且≤deg的非负整数组合(排除全零的偏置项)
    exponents = filter(x -> sum(x) ≥ 1 && sum(x) ≤ deg, collect(Iterators.product(fill(0:deg, s)...)))
    exponents = collect.(exponents)
    
    # 预分配结果矩阵
    p = similar(mat, n, length(exponents))
    varnm = String[]
    
    for (k, exp) in enumerate(exponents)
        # 计算当前特征列:各特征的指数幂相乘
        col = ones(eltype(mat), n)
        for (i, e) in enumerate(exp)
            e > 0 && (col .*= mat[:, i] .^ e)
        end
        p[:, k] = col
        
        # 生成特征名称
        parts = String[]
        for (i, e) in enumerate(exp)
            if e == 1
                push!(parts, string(vars[i]))
            elseif e > 1
                push!(parts, "$(vars[i])^$e")
            end
        end
        push!(varnm, join(parts, "*"))
    end
    
    return p, varnm
end

这个版本可以处理任意阶数的多项式特征,而且同样通过预分配内存和广播操作保证了效率。


内容的提问来源于stack exchange,提问作者delight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:05:17