在进行多项式回归的时候,通常需要将特征转换到多项式特征,比如有如下特征,
$$ x_1,x_2,...,x_n $$
要将其转换为二项特征,那么转换之后的特征则是:
$$ 1,x_1,x_2,..,x_n,x_1x_1, x_1x_2,...,x_1x_n,...,x_2x_2,...x_nx_n $$
假设数据为:
import numpy as np
x = np.array([[1, 2],[3, 4]])
x
array([[1, 2],
[3, 4]])
使用sklearn
库来实现
代码如下:
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2)
poly.fit_transform(x)
array([[ 1., 1., 2., 1., 2., 4.],
[ 1., 3., 4., 9., 12., 16.]])
我的实现
代码如下:
import itertools
import functools
import numpy as np
class PolynomialFeatures(object):
def __init__(self, degree=2):
assert isinstance(degree, int)
self.degree = degree
def transform(self, x):
# 如果特征只有1维,就将其转换为nx1矩阵
if x.ndim == 1:
x = x[:, None]
# 转置一下,方便后面按列来叠加相乘
x_t = x.T
# 准备返回的新特征矩阵,第一列是常数项(偏置),所以全部为1
features = [np.ones(len(x))]
# 每个degree循环创建该级别的多项特征,从1到self.degree + 1
for degree in range(1, self.degree + 1):
# 第二个循环用到itertools.combinations_with_replacement
# 第1个参数是个列表,第2个参数是个正整数,假设记为n
# 返回的是一个生成器,是列表中所有n个元素的组合,包含元素与自身的组合
# 比如itertools.combinations_with_replacement([1,2,3],2)
# 那么结果为:
# [(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
# 这里第1个参数是x的转置,转换成了列,也就是列的组合
for items in itertools.combinations_with_replacement(x_t, degree):
# functools.reduce是根据列表中数值按顺序做lambda,并且把前一次得到的
# 值保存下来,再与下一次的值来做lambda运算,官方的例子:
# reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
# 计算的是:((((1+2)+3)+4)+5)
# 这里就是将每一列叠加相乘,之后再放到features中
features.append(functools.reduce(lambda x, y : x * y, items))
# 转置回来,并将其返回
return np.asarray(features).T
my_poly = PolynomialFeatures(2)
my_poly.transform(x)
array([[ 1., 1., 2., 1., 2., 4.],
[ 1., 3., 4., 9., 12., 16.]])