特征工程(如何合理地把非数值特征转换成数值特征)
现在我理解的特征工程的意义是:如何把非数值特征转换成数值特征?
1、假如有一个属性是职业,有这三种职业,教师、公务员、工程师,现在要用一个基于线性回归的算法,来训练模型,假如f(x,y)=ax+by,a,b代表权重,x代表职业这个属性值,那么如何给这个x赋值?
解决方案:
1、人工无脑的赋值,比如教师=1,公务员=2,工程师=3,但是这样科学吗?假设教师和工程师的特征比较相似,这样显然不合适。但是,这种方法依然在用,解决这种不合理的办法是,世界上有许多计算词汇相似度的方法,他能判别各种词汇的相似度,我们根据词汇相似度然后再给他们赋值。
2、离散赋值,比如把职业这个属性再分为三类
</article>
【特征工程】 离散型变量 映射成 数字
在特征处理中,有一些特征里面的值是一些可分类的字符串,举个例子:
姓名 | 学历 | 收入 |
---|---|---|
小张 | 高中 | 4000-5000元 |
小王 | 本科 | 6000-7000元 |
小李 | 硕士 | 8000-9000元 |
小赵 | 本科 | 6000-7000元 |
… | … | … |
学历可分为:高中、大专、本科、硕士等。收入可分为:4000-5000元、6000-7000元等。这些分类有时为中文,容易产生乱码。有些是英文字符,可能比较长,查看不方便。如果样本量非常多的话,保存下来的文件较大。
所以可以将 高中→1,大专→2,本科→3 ···;4000-5000元→1、6000-7000元→2 ···
这些特征工程处理上,可以对这种可分类的字符串进行替换,映射成一组数字去替换。但需要注意的是,虽然用数字替换,但数字仅仅是各分类变量的一个替换,并没有真正意义的数字含义,所以不能比较大小,也不能当成连续字符处理。
下面给出了批量替换的代码。
首先是将字符串映射成数字,然后逐列操作。
## 分类变量→数字的映射
def str2num(col_name):
value_dict = {}
unique_str = np.unique(col_name)
for num,value in enumerate(unique_str, start=1):
value_dict[value] = num
return value_dict
## 寻找字符串类型的特征,并进行映射
def use_dict(df):
str2num_dict = {}
obj_feature = df.dtypes[df.dtypes=="object"].index
for obj in obj_feature:
str2num_dict[obj] = str2num(df[obj].astype("str"))
return str2num_dict
上面使用.astype("str")
在一些情况下是必须的,否则会报错,使用后,缺失值都会被转化成字符串nan
。
为了以后可以直接应用,需要将字典进行保存,保存成pickle文件。
import pickle
## run data
str2num_dict = use_dict(data)
## save dict
with open("str2num_dict.pkl",'wb') as f:
pickle.dump(str2num_dict,f)
之后每个样本需要应用,直接读取即可,读取命令如下。
# Loading dict and apply
with open("str2num_dict.pkl",'rb') as f:
str2num_dict = pickle.load(f)
应用时直接使用下面命令对训练数据和待测样本进行操作。
import numpy as np
for i in str2num_dict.keys():
data_train[i] = data_train[i].apply(str).apply(lambda x : str2num_dict[i].get(x, np.nan))
# 无测试集下面可忽略
data_test[i] = data_test[i].apply(str).apply(lambda x : str2num_dict[i].get(x, np.nan))
这里还是需要先做.apply(str)
转化,可以将缺失值转化后字符串nan
后,再做映射。
假如需要映射的字段里出现了新的类型,还是会被转化为缺失值。