基于Keras ANN的旧金山犯罪预测:日期特征转换与小时独热编码咨询
处理SF Crime数据集的特征转换(Keras ANN建模)
针对你用Keras构建ANN处理SF Crime数据集的几个特征转换问题,我给你整理了具体的实现方法和建议:
1. 将DayOfWeek转换为工作日/周末二值特征
假设你的DataFrame列DayOfWeek存储的是类似"Monday"、"Sunday"这样的字符串,两种简单的实现方式:
方法一:用Pandas isin()(推荐,性能更优)
这种方法对大数据集更友好,逻辑也直观:
# 定义周末的日期列表 weekend_list = ["Saturday", "Sunday"] # 生成二值列:周末为1,工作日为0 df["is_weekend"] = df["DayOfWeek"].isin(weekend_list).astype(int)
方法二:用lambda函数+apply()
如果更习惯lambda的写法,也可以这样实现:
df["is_weekend"] = df["DayOfWeek"].apply(lambda x: 1 if x in ["Saturday", "Sunday"] else 0)
2. 将月份映射为四季类别特征
首先明确月份到四季的映射逻辑(可根据需求调整):
- 冬季:12、1、2
- 春季:3、4、5
- 夏季:6、7、8
- 秋季:9、10、11
同样有两种常见实现方式:
方法一:字典映射+map()(推荐,代码更易维护)
用字典存储映射关系,后续调整季节划分时只需修改字典:
season_mapping = { 1: "Winter", 2: "Winter", 12: "Winter", 3: "Spring", 4: "Spring", 5: "Spring", 6: "Summer", 7: "Summer", 8: "Summer", 9: "Fall", 10: "Fall", 11: "Fall" } # 假设Month列是整数类型(1-12),如果是字符串需先转int:df["Month"] = df["Month"].astype(int) df["season"] = df["Month"].map(season_mapping)
方法二:lambda函数+apply()
如果不想额外定义字典,也可以用嵌套条件的lambda:
df["season"] = df["Month"].apply( lambda x: "Winter" if x in [1, 2, 12] else "Spring" if x in [3, 4, 5] else "Summer" if x in [6, 7, 8] else "Fall" )
注意:如果之后要把
season喂给Keras模型,需要将这个类别特征进一步转换(比如用pd.get_dummies()做独热编码,或者用Keras的嵌入层)。
3. Hour值的独热编码建议
Hour是0-23的离散数值,独热编码是可行的,但也有其他更高效的处理方式,给你几个选项:
选项一:传统独热编码(简单直接)
用Pandas的get_dummies()快速生成独热编码列:
# 生成前缀为hour的独热编码列 hour_onehot = pd.get_dummies(df["Hour"], prefix="hour") # 合并到原DataFrame df = pd.concat([df, hour_onehot], axis=1) # 可选:删除原Hour列 df.drop("Hour", axis=1, inplace=True)
这种方式生成24个特征列,对于大部分数据集来说不会造成维度爆炸,适合快速实现。
选项二:在Keras模型内处理独热编码
如果不想在预处理阶段做编码,可以直接在模型中加入CategoryEncoding层:
from keras.layers import Input, CategoryEncoding # 定义Hour的输入层 hour_input = Input(shape=(1,)) # 0-23共24个类别,output_mode设为one_hot hour_encoded = CategoryEncoding(num_tokens=24, output_mode="one_hot")(hour_input)
这种方式更适合端到端的建模流程。
选项三:更高效的特征转换(推荐考虑)
如果想减少特征维度同时保留时间信息,可以试试以下两种方式:
- 分时段编码:将Hour合并为更粗的时段(如凌晨、上午、下午、晚上),再做独热编码,仅生成4个特征列:
df["time_period"] = df["Hour"].apply( lambda x: "night" if 0 <= x < 6 else "morning" if 6 <= x < 12 else "afternoon" if 12 <= x < 18 else "evening" ) # 对时段做独热编码 period_onehot = pd.get_dummies(df["time_period"], prefix="period") df = pd.concat([df, period_onehot], axis=1)
- 循环编码(Cyclical Encoding):将Hour转换为sin和cos值,捕捉时间的周期性(比如23点和0点的相似性),仅生成2个特征列:
import numpy as np df["hour_sin"] = np.sin(2 * np.pi * df["Hour"] / 24) df["hour_cos"] = np.cos(2 * np.pi * df["Hour"] / 24)
这种方式维度极低,还能让模型学习到时间的循环规律,适合对效率要求较高的场景。
内容的提问来源于stack exchange,提问作者UHU
相关产品推荐
相关产品推荐

