数据表示与特征工程
目前为止,数据都是浮点数的二维数据,而且横着那一排还是个连续特征(continue feature),实际上生活中基本是分类特征(categorical feature),也叫离散特征(discrete feature),且不是数值呢。且我们知道数据缩放很重要,同样的用额外的特征扩充(augment)数据也很有帮助,比如添加特征的交互项呢。
特征工程(feature engineering),在监督模型中有时比调参牛逼。
1.分类变量
会发现特征有的连续,有的表示的定性属性。如果要用通过Logistic回归,我们知道他的x一定是数字,而在这里可能是字符串,因此我们需要解决这个问题呢
1.1.One-Hot编码(虚拟变量)
表示分类变量的最常用的方法就是One-Hot编码(one-hot-encoding)或N取一编码(one-out-of-N encoding),也叫虚拟变量(dummy variable)。比如特征A取值包含a, b, c, d这4个,如果 A 取值为 a ,则对应的特征 a 取值1,其余0。意思就是一个特征变成了 n 个它的可能取值的特征。
为毛只取0、1呢,为了简化分析,也就是避免使数据矩阵秩亏
使用pandas 从逗号分割值文件中加载数据
from IPython.display import display
# 文件中没有包含列名称的表头,因此我们传入header=None
# 然后在“names”中显式地提供列名称
data = pd.read_csv(
"D:\\MyCodeWork\\PC_Code\\project1\\data\\adult.data", header=None, index_col=False,
names=['age', 'workclass', 'fnlwgt', 'education', 'education-num',
'marital-status', 'occupation', 'relationship', 'race', 'gender',
'capital-gain', 'capital-loss', 'hours-per-week', 'native-country',
'income'])
# 为了便于说明,我们只选了其中几列
data = data[['age', 'workclass', 'education', 'gender', 'hours-per-week',
'occupation', 'income']]
display(data.head())
1.1.1.检查字符串编码的分类数据
检查每一列是否包含有意义的分类数据。因为有的憨批喜欢把 male 写个 Male Man 什么的玩意儿= =。可以借助pandas Series的 value_counts 函数,以显示类别及次数
print(data.gender.value_counts())
pandas 里的 get_dummies 可以把一转 N = =
print("Original features:\n", list(data.columns), "\n")
data_dummies = pd.get_dummies(data)
print("Feature after get_dummies:\n", list(data_dummies.columns))
下面使用 values 属性将 data_dummies 数据框转化为 NumPy 数组,然后训练数据模型,但是!must remember 把目标变量(后两列)从数据中分离出来。
注意:pandas 中的索引包括范围的结尾,而 NumPy 不包括呢!
我们提取包含特征的列
features = data_dummies.ix[:, 'age': 'occupation_ Transport-moving']
# 提取数组
X = features.values
y = data_dummies['income_ >50K'].values
print("X.shape: {} y.shape: {}".format(X.shape, y.shape))
Here we go
from sklearn.linear_model import LogisticRegression
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
logreg = LogisticRegression()
logreg.fit(X_train, y_train)
print("Test score: {:.2f}".format(logreg.score(X_test, y_test)))
这个例子中,我们对训练集和测试集统一处理, 表示方式相同呢。不然,比如特征 A 在训练集里由10个类别,而在测试集里只有3个,那是不是很不公平,那么 pandas 处理后它们不一样长诶。
1.2数字可以编码分类变量
通常我们填个啥表就是在那几个框框里打勾勾,所以那么结果就可以用几个数值表示呢。
分类特征通常使用数字编码,如果变么的语义之间没有顺序关系的话,那么特征 must 被视为离散的哟~~(^U^)ノ~YO
pandas 的 get_dummies 函数将所有数字看作是连续的,不会为其创建虚拟变量。可以用 scikit-learn 的 OneHotEncoder,指定哪些变量连续、离散,也可以将数据框中的数值列转换为字符串。
# 创建一个DataFrame,包含一个整数特征和一个分类字符串特征
demo_df = pd.DataFrame({'Integer Feature': [0, 1, 2, 1],
'Categorical Feature': ['socks', 'fox', 'socks', 'box']})
display(demo_df)
使用 get_dummies 指挥编码字符串特征,不会改变整数特征
display(pd.get_dummies(demo_df))
改变了字符串,没改变整数,要改变整数,可以使用 columns 参数显式地给出想要编码的列。
demo_df['Integer Feature'] = demo_df['Integer Feature'].astype(str)
display(pd.get_dummies(demo_df, columns=['Integer Feature', 'Categorical Feature']))
2.分箱、离散化、线性模型与树
数据表示的最佳方法不仅取决于数据的语义,还取决于所使用的模型种类,线性模型于基于树的模型(决策树、梯度提升树、随机森林)很常用。接下来比较线性回归和决策树呢
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
X, y = mglearn.datasets.make_wave(n_samples=100)
line = np.linspace(-3, 3, 1000, endpoint=False).reshape(-1, 1)
reg = DecisionTreeRegressor(min_samples_split=3).fit(X, y)
plt.plot(line, reg.predict(line), label="decision tree")
reg = LinearRegression().fit(X, y)
plt.plot(line, reg.predict(line), label="linear regression")
plt.plot(X[:, 0], y, 'o', c='k')
plt.ylabel("Regression output")
plt