机器学习之特征工程
文章目录
- 特征工程概述
- 有价值特征的特点
- 特征工程的步骤
- 常用的特征工程工具与实际应用
- Scikit - learn库实际案例
- 图像数据处理 - TensorFlow
- 图像数据处理 - PyTorch
- 语音数据处理 - TensorFlow
- 语音数据处理 - PyTorch
特征工程概述
- 特征工程是什么:特征工程是将原始数据转化为更能代表预测目标的特征的过程,涉及数据预处理、特征提取、特征选择和特征构造等多个环节,目的是让数据更好地适应机器学习模型,提高模型的性能和效果。
- 特征工程的价值
- 提升模型性能:通过提取和选择有代表性的特征,帮助模型更准确地捕捉数据中的规律,从而提高模型的准确性、泛化能力等性能指标。
- 降低模型复杂度:去除无关或冗余的特征,减少模型训练的参数数量,降低模型过拟合的风险,同时提高模型的训练速度和效率。
- 增强数据理解:在特征工程过程中,深入了解数据的特点和内在关系,有助于发现数据中的异常、规律和潜在信息,为后续的数据分析和决策提供支持。
有价值特征的特点
- 与目标变量相关性高:特征与预测目标之间存在较强的线性或非线性关系,能够直接或间接地反映目标变量的变化趋势。
- 具有区分度:在不同的样本类别或目标值之间,特征的值有明显的差异,能够有效地区分不同的样本。
- 稳定性好:在不同的数据集或数据分布下,特征的表现相对稳定,不会因为数据的微小变化而产生较大波动,保证模型的可靠性和泛化能力。
- 可解释性强:特征具有明确的物理意义或业务含义,易于理解和解释,方便与他人沟通和交流,也有助于对模型结果进行分析和验证。
特征工程的步骤
- 数据预处理:包括缺失值处理、异常值处理、数据标准化与归一化等,以提高数据质量,为后续分析做准备。
- 特征提取:根据数据类型和特点,运用各种方法将原始数据转换为特征向量,如对文本数据使用词袋模型、TF - IDF等,对图像数据使用卷积神经网络等。
- 特征选择:从提取的特征中挑选出对模型最有价值的特征子集,可采用过滤式、包裹式、嵌入式等方法。
- 特征构造:通过组合原始特征、构造多项式特征或利用领域知识创造新的特征,增加特征的多样性和表达能力。
常用的特征工程工具与实际应用
Scikit - learn库实际案例
数据预处理
- StandardScaler:假设我们有一个包含多个特征的数据集,例如一个关于不同商品销售数据的数据集,其中包含价格、销量、利润等特征。这些特征的量纲不同,价格可能在几十到几千元之间,而销量可能在几百到几万件之间。使用
StandardScaler
对数据进行标准化处理,将每个特征的均值调整为0,标准差调整为1。这样可以使不同特征在模型训练中具有相同的重要性,避免因量纲差异导致模型偏向于某些特征。以下是示例代码:
from sklearn.preprocessing import StandardScaler
import numpy as np
# 示例数据
data = np.array([[100, 500, 1000], [200, 800, 1500], [300, 1000, 2000]])
scaler = StandardScaler()
scaled_data = scaler.fit_transform(data)
print(scaled_data)
- MinMaxScaler:仍以上述商品销售数据为例,如果希望将数据归一化到0 - 1的区间内,可以使用
MinMaxScaler
。它会将每个特征的值映射到指定的区间内,通过将特征的最小值映射到0,最大值映射到1,其他值按比例进行缩放。示例代码如下:
from sklearn.preprocessing import MinMaxScaler
import numpy as np
# 示例数据
data = np.array([[100, 500, 1000], [200, 800, 1500], [300, 1000, 2000]])
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data)
print(scaled_data)
特征提取
- CountVectorizer:假设我们有一个文本分类任务,例如对新闻文章进行分类。首先需要将文本数据转换为特征向量。使用
CountVectorizer
可以将文本中的单词转换为向量表示,统计每个单词在文本中出现的次数。例如,有以下几篇新闻文章:[“苹果公司发布了新款手机”, “华为推出了创新的通信技术”, “苹果和华为在市场上竞争激烈”]。代码示例如下:
from sklearn.feature_extraction.text import CountVectorizer
# 示例文本数据
texts = ["苹果公司发布了新款手机", "华为推出了创新的通信技术", "苹果和华为在市场上竞争激烈"]
vectorizer = CountVectorizer()
vectorized_texts = vectorizer.fit_transform(texts)
print(vectorized_texts.toarray())
print(vectorizer.get_feature_names())
- TfidfVectorizer:在上述新闻文章分类任务中,
TfidfVectorizer
不仅考虑了单词在文本中的出现次数(词频,TF),还考虑了单词在整个语料库中的稀有程度(逆文档频率,IDF)。通过这种方式,能够更准确地衡量每个单词对于文本分类的重要性。示例代码如下:
from sklearn.feature_extraction.text import TfidfVectorizer
# 示例文本数据
texts = ["苹果公司发布了新款手机", "华为推出了创新的通信技术", "苹果和华为在市场上竞争激烈"]
vectorizer = TfidfVectorizer()
vectorized_texts = vectorizer.fit_transform(texts)
print(vectorized_texts.toarray())
print(vectorizer.get_feature_names())
特征选择
- SelectKBest:假设我们有一个数据集,包含多个特征,我们希望选择出对目标变量最具预测能力的 (K) 个特征。例如,在一个预测客户是否会购买某产品的数据集上,有客户的年龄、收入、教育程度、购买历史等多个特征。使用
SelectKBest
可以根据某个统计量(如卡方检验)来选择 (K) 个最佳特征。示例代码如下:
from sklearn.feature_selection import SelectKBest, chi2
import numpy as np
# 示例数据
X = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
y = np.array([0, 1, 0, 1])
selector = SelectKBest(chi2, k=2)
X_new = selector.fit_transform(X, y)
print(X_new)
- LassoCV:在一个线性回归问题中,使用
LassoCV
进行特征选择。它通过在目标函数中加入L1正则化项,使得一些特征的系数变为0,从而实现特征选择的目的。同时,LassoCV
还通过交叉验证来选择最优的正则化参数。例如,我们有一个关于房价预测的数据集,包含房屋面积、房间数量、房龄等多个特征。示例代码如下:
from sklearn.linear_model import LassoCV
import numpy as np
# 示例数据
X = np.array([[100, 5, 10], [150, 6, 5], [200, 8, 3]])
y = np.array([100000, 150000, 200000])
lasso = LassoCV(cv=5).fit(X, y)
print(lasso.coef_)
在上述代码中,lasso.coef_
输出的结果中接近0的系数对应的特征就是被LassoCV认为不太重要的特征,从而实现了特征选择的功能。
以下是TensorFlow和PyTorch在处理图像和语音等复杂数据时,通过构建深度神经网络模型自动进行特征工程的案例:
图像数据处理 - TensorFlow
在图像分类任务中,常常使用卷积神经网络(CNN)来自动提取图像特征。以MNIST手写数字识别为例:
- 数据准备:
import tensorflow as tf from tensorflow.keras.datasets import mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() # 归一化图像数据到0-1区间 x_train, x_test = x_train / 255.0, x_test / 255.0 # 增加通道维度,因为MNIST数据是灰度图,通道数为1 x_train = x_train[..., tf.newaxis] x_test = x_test[..., tf.newaxis]
- 构建模型:
model = tf.keras.models.Sequential([ # 第一个卷积层,32个3x3的卷积核,激活函数为ReLU tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)), # 最大池化层,池化窗口为2x2 tf.keras.layers.MaxPooling2D((2, 2)), # 第二个卷积层,64个3x3的卷积核,激活函数为ReLU tf.keras.layers.Conv2D(64, (3, 3), activation='relu'), # 最大池化层,池化窗口为2x2 tf.keras.layers.MaxPooling2D((2, 2)), # 将卷积层的输出展平为一维向量 tf.keras.layers.Flatten(), # 全连接层,128个神经元,激活函数为ReLU tf.keras.layers.Dense(128, activation='relu'), # 输出层,10个神经元,对应10个数字类别,激活函数为softmax tf.keras.layers.Dense(10, activation='softmax') ])
- 编译与训练模型:
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test))
在这个案例中,CNN中的卷积层和池化层自动提取了图像的特征,如边缘、角点等低级特征,随着网络的加深,逐渐提取出更高级的特征,如数字的整体形状等,无需人工手动设计图像特征。
图像数据处理 - PyTorch
同样以MNIST手写数字识别为例:
- 数据准备:
import torch import torchvision from torchvision import transforms # 定义数据预处理步骤,包括归一化和转换为张量 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) # 加载MNIST训练集和测试集 train_dataset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform) test_dataset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform) # 创建数据加载器,用于批量加载数据 train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False)
- 构建模型:
import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() # 第一个卷积层,1个输入通道,32个输出通道,卷积核大小为3x3 self.conv1 = nn.Conv2d(1, 32, 3) # 第二个卷积层,32个输入通道,64个输出通道,卷积核大小为3x3 self.conv2 = nn.Conv2d(32, 64, 3) # 全连接层,用于将卷积层的输出映射到类别空间 self.fc1 = nn.Linear(64 * 5 * 5, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): # 卷积层1,使用ReLU激活函数和最大池化 x = F.relu(self.conv1(x)) x = F.max_pool2d(x, 2) # 卷积层2,使用ReLU激活函数和最大池化 x = F.relu(self.conv2(x)) x = F.max_pool2d(x, 2) # 将特征图展平为一维向量 x = x.view(-1, 64 * 5 * 5) # 全连接层1,使用ReLU激活函数 x = F.relu(self.fc1(x)) # 全连接层2,输出类别概率 x = self.fc2(x) return x model = Net()
- 定义损失函数和优化器并训练模型:
criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) for epoch in range(5): for images, labels in train_loader: optimizer.zero_grad() outputs = model(images) loss = criterion(outputs, labels) loss.backward() optimizer.step() # 在测试集上评估模型 correct = 0 total = 0 with torch.no_grad(): for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy on test set: {} %'.format(100 * correct / total))
在PyTorch的CNN模型中,通过卷积层、池化层等操作自动从图像数据中学习到了有代表性的特征,实现了特征工程的自动化。
语音数据处理 - TensorFlow
以语音识别任务为例,使用深度神经网络(DNN)结合梅尔频率倒谱系数(MFCC)特征进行语音识别:
- 数据准备:
- 首先需要收集语音数据集,例如TIMIT数据集。
- 对语音信号进行预处理,包括分帧、加窗、计算MFCC特征等。可以使用
python_speech_features
库来计算MFCC。
import librosa from python_speech_features import mfcc def extract_mfcc(file_path): # 加载语音文件 audio, sr = librosa.load(file_path, sr=None) # 计算MFCC特征 mfcc_features = mfcc(audio, samplerate=sr) return mfcc_features # 假设train_files和test_files分别是训练集和测试集的文件路径列表 train_features = [extract_mfcc(file_path) for file_path in train_files] test_features = [extract_mfcc(file_path) for file_path in test_files] # 将特征转换为numpy数组,并进行归一化等预处理 train_features = np.array(train_features) test_features = np.array(test_features) train_features = (train_features - np.mean(train_features, axis=0)) / np.std(train_features, axis=0) test_features = (test_features - np.mean(test_features, axis=0)) / np.std(test_features, axis=0)
- 构建模型:
model = tf.keras.models.Sequential([ # 第一个全连接层,128个神经元,激活函数为ReLU tf.keras.layers.Dense(128, activation='relu', input_shape=(train_features.shape[1],)), # 第二个全连接层,64个神经元,激活函数为ReLU tf.keras.layers.Dense(64, activation='relu'), # 输出层,对应不同的语音类别,激活函数为softmax tf.keras.layers.Dense(num_classes, activation='softmax') ])
- 编译与训练模型:
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) model.fit(train_features, train_labels, epochs=10, validation_data=(test_features, test_labels))
在这个案例中,虽然手动提取了MFCC作为初始特征,但深度神经网络在训练过程中进一步自动学习了这些特征的组合和抽象,以更好地完成语音识别任务。
语音数据处理 - PyTorch
同样以语音识别为例,使用卷积神经网络(CNN)结合MFCC特征:
- 数据准备:
- 与TensorFlow案例中的数据准备步骤类似,先收集语音数据集,计算MFCC特征,并进行预处理。
- 将数据整理成PyTorch的
Dataset
和DataLoader
格式。
class SpeechDataset(torch.utils.data.Dataset): def __init__(self, features, labels): self.features = features self.labels = labels def __len__(self): return len(self.features) def __getitem__(self, idx): feature = self.features[idx] label = self.labels[idx] return torch.tensor(feature, dtype=torch.float32), torch.tensor(label, dtype=torch.long) train_dataset = SpeechDataset(train_features, train_labels) test_dataset = SpeechDataset(test_features, test_labels) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False)
- 构建模型:
class SpeechCNN(nn.Module): def __init__(self): super(SpeechCNN, self).__init__() # 第一个卷积层,1个输入通道,32个输出通道,卷积核大小为3x3 self.conv1 = nn.Conv2d(1, 32, (3, 3)) # 第二个卷积层,32个输入通道,64个输出通道,卷积核大小为3x3 self.conv2 = nn.Conv2d(32, 64, (3, 3)) # 全连接层 self.fc1 = nn.Linear(64 * 10 * 10, 128) self.fc2 = nn.Linear(128, num_classes) def forward(self, x): # 增加通道维度 x = x.unsqueeze(1) # 卷积层1,使用ReLU激活函数和最大池化 x = F.relu(self.conv1(x)) x = F.max_pool2d(x, (2, 2)) # 卷积层2,使用ReLU激活函数和最大池化 x = F.relu(self.conv2(x)) x = F.max_pool2d(x, (2, 2)) # 将特征图展平为一维向量 x = x.view(-1, 64 * 10 * 10) # 全连接层1,使用ReLU激活函数 x = F.relu(self.fc1(x)) # 全连接层2,输出类别概率 x = self.fc2(x) return x model = SpeechCNN()
- 定义损失函数和优化器并训练模型:
criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) for epoch in range(10): for features, labels in train_loader: optimizer.zero_grad() outputs = model(features) loss = criterion(outputs, labels) loss.backward() optimizer.step() # 在测试集上评估模型 correct = 0 total = 0 with torch.no_grad(): for features, labels in test_loader: outputs = model(features) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy on test set: {} %'.format(100 * correct / total))
在这个PyTorch案例中,CNN模型自动对MFCC特征进行了进一步的特征提取和优化,通过卷积和池化操作学习到了更具代表性的语音特征,用于语音识别任务。