df = pd.read_excel('數據.xlsx')
print("原始數據特征:",df.drop(['price'], axis=1).columns)
print("原始數據特征數:",len(df.drop(['price'], axis=1).columns))
df
這里原始數據刨除因變量price只存在7個特征,將在這個基礎上在想象力范圍能組合出盡可能多的特征
等頻分箱
# 提取自變量特征
X = df.drop(['price'], axis=1)
# 獲取所有列名并轉換為列表以適合特定輸入格式
variables = X.columns.tolist()
from feature_engine.discretisation import EqualFrequencyDiscretiser
from feature_engine.transformation import LogTransformer, PowerTransformer
# 創建等頻分箱器
discretizer = EqualFrequencyDiscretiser(q=4, variables=variables)
X_1 = discretizer.fit_transform(X)
# 重命名分箱后的列名
new_column_names = {col: f"{col}_分箱" for col in X_1.columns}
X_1.rename(columns=new_column_names, inplace=True)
X_1
等頻分箱是一種將連續變量轉化為離散變量的技術,其原理是將數據排序后,將排序后的數據等頻率地劃分為指定數量的區間(分箱),每個分箱內包含的數據點數量大致相同
對數變換
# 對數變換前 確保沒有零或負值
# 對數變換
log_transformer = LogTransformer(variables=variables)
X_2 = log_transformer.fit_transform(X)
# 重命名對數變換后的列名
new_column_names = {col: f"{col}_對數" for col in X_2.columns}
X_2.rename(columns=new_column_names, inplace=True)
X_2
對數變換將特征值拉伸或壓縮,從而減少數據的偏度,平滑數據分布,適合于具有正偏態或長尾分布的數據
冪變換
# 冪變換
power_transformer = PowerTransformer(variables=variables, exp=0.5)
X_3 = power_transformer.fit_transform(X)
# 重命名對數變換后的列名
new_column_names = {col: f"{col}_冪變換" for col in X_3.columns}
X_3.rename(columns=new_column_names, inplace=True)
X_3
冪變換用于通過對數據進行冪函數變換來減小偏度和改善數據的正態性
一些數學特征變化
# 創建一個字典來存儲新特征
new_features = {}
# 添加數學特征到字典中
for feature in variables:
for other_feature in variables:
if feature != other_feature:
# 創建新的特征,表示兩個特征的加和
new_features[f'{feature}_plus_{other_feature}'] = df[feature] + df[other_feature]
# 創建新的特征,表示兩個特征的差
new_features[f'{feature}_minus_{other_feature}'] = df[feature] - df[other_feature]
# 創建新的特征,表示兩個特征的乘積
new_features[f'{feature}_times_{other_feature}'] = df[feature] * df[other_feature]
# 創建新的特征,表示兩個特征的商
new_features[f'{feature}_div_by_{other_feature}'] = df[feature] / df[other_feature]
# 將新特征轉為數據框
X_4 = pd.DataFrame(new_features)
X_4
data = pd.concat([X, X_1, X_2, X_3, X_4], axis=1)
print("暴力數據特征:",data.columns)
print("暴力數據特征數:",len(data.columns))
通過上述特征工程步驟,從最初的7個特征擴展到196個特征,這種暴力特征工程方法有助于提供更多的信息和特征組合,從而提高模型的預測精度,當然這里是作者的暴力特征工程,讀者可拓寬自己對特征工程的想象力,以此來得到更多的特征
篩選特征貢獻度前20名
from sklearn.model_selection import train_test_split
X_temp, X_test, y_temp, y_test = train_test_split(data, df['price'], test_size=0.2, random_state=42)
# 然后將訓練集進一步劃分為訓練集和驗證集
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.125, random_state=42) # 0.125 x 0.8 = 0.1
import xgboost as xgb
# XGBoost參數
params_xgb = {
'learning_rate': 0.02,
'booster': 'gbtree',
'objective': 'reg:squarederror',
'max_leaves': 127,
'verbosity': 1,
'seed': 42,
'nthread': -1,
'colsample_bytree': 0.6,
'subsample': 0.7,
'early_stopping_rounds': 100,
'eval_metric': 'rmse'
}
# 初始化模型
model_xgb = xgb.XGBRegressor(**params_xgb)
# 訓練模型
model_xgb.fit(X_train, y_train, eval_set=[(X_val, y_val)], verbose=False)
# 提取特征重要性
feature_importances = model_xgb.feature_importances_
# 創建一個DataFrame,包含特征名稱和對應的重要性
importance_df = pd.DataFrame({
'Feature': X_train.columns,
'Importance': feature_importances
})
# 按重要性排序
importance_df = importance_df.sort_values(by='Importance', ascending=False)
# 選擇排名前20的特征
top_20_features = importance_df.head(20)
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 可視化
plt.figure(figsize=(15, 5), dpi=600)
plt.barh(top_20_features['Feature'], top_20_features['Importance'], color='skyblue')
plt.xlabel('Feature Importance')
plt.ylabel('Feature Name')
plt.title('Top 20 Feature Importances')
plt.gca().invert_yaxis()
plt.show()
通過特征工程生成新特征,使用XGBoost模型訓練和評估數據,篩選出最重要的20個特征,以指導進一步的特征選擇和工程,反復迭代和優化,從而提高模型的精確度
本文章轉載微信公眾號@Python機器學習AI