device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
############################################
# 1. 数据预处理
############################################
# 【1.1】读取数值型数据(用于原始数据分支)
# 原来的数据预处理,替换 Y/N/?,并归一化;标签根据 list_y 得到索引。
list_y = ['WWW', 'MAIL','FTP-DATA', 'FTP-PASV','FTP-CONTROL','SERVICES','DATABASE' ,'P2P', 'ATTACK', 'MULTIMEDIA', 'INTERACTIVE', 'GAMES']
# 定义离散特征对应的列名和映射字典
feature_cols = ["col_65", "col_66", "col_67", "col_68", "col_71", "col_72"]
label_mappings = {
'col_65': {'Y': 'Window_Scaling_cs', 'N': 'no_Window_Scaling_cs'},
'col_66': {'Y': 'Time_Stamp_cs', 'N': 'no_Time_Stamp_cs'},
'col_67': {'Y': 'Window_Scaling_sc', 'N': 'no_Window_Scaling_sc'},
'col_68': {'Y': 'Time_Stamp_sc', 'N': 'no_Time_Stamp_sc'},
'col_71': {'Y': 'SACK_cs', 'N': 'no_SACK_cs'},
'col_72': {'Y': 'SACK_sc', 'N': 'no_SACK_sc'}
}
# 离散型特征在原始文件中的列索引(注意:索引从0开始)
discrete_indices = [64, 65, 66, 67, 70, 71]
def data_prepross_numeric(filenames):
X, Y = [], []
for f in filenames:
print("Processing numeric file:", f)
with open(os.path.join(os.getcwd(), f), 'r') as file:
# 跳过头部信息
for line in file.readlines()[253:]:
#strip()去掉字符串两端的空格或换行符,确保处理后的字符串干净
# 保留原始行,不做 Y/N 替换,这里只做 strip(),后面我们会用离散规则进行过滤
line = line.strip().replace('?', '0')
parts = line.split(',')
row = []
# 对前面除标签外的所有列进行处理
for i, x in enumerate(parts[:-1]):
if i in discrete_indices:
# 离散型:直接保留原始字符串(如 "Y", "N", "?")
row.append(x.strip())
else:
# 其它列按 float 转换
row.append(float(x))
# 按原逻辑末尾补8个0(这部分可以认为是数值型数据)
row.extend([0] * 8)
# 标签处理,修正拼写错误后根据 list_y 得到索引
label = parts[-1].replace('FTP-CO0TROL', 'FTP-CONTROL') \
.replace('I0TERACTIVE', 'INTERACTIVE').strip()
label_idx = list_y.index(label)
X.append(row)
Y.append(label_idx)
# 注意:由于存在离散型列存为字符串,不能直接用 np.array(..., dtype=np.float32)
# 此处返回原始列表和标签(标签可以转换为 numpy 数组)
return X, np.array(Y)
# 读取数据
filenames = ['MooreDataset/entry01.weka.allclass.arff']
X_raw, total_labels = data_prepross_numeric(filenames)
# 将 X_raw 转换为 DataFrame方便后续处理
df_total = pd.DataFrame(X_raw)
############################################
# 2. 离散型特征处理与样本过滤
############################################
# 从 df_total 中提取离散型部分:第65,66,67,68,71,72列(对应索引 64,65,66,67,70,71)
df_discrete = df_total.iloc[:, discrete_indices].copy()
df_discrete.columns = feature_cols
# 加入 protocol 列(供检查使用)
df_discrete["protocol"] = [list_y[label] for label in total_labels]
# 对这六个离散列做映射:先用映射字典将 "Y"/"N" 转换为描述字符串
# (注意:原始数据中这些列应当只有 "Y", "N", 或 "?"(0))
for col in feature_cols:
df_discrete[col] = df_discrete[col].map(label_mappings[col])
# 过滤掉任一离散型特征映射后为 NaN 的样本
df_discrete_valid = df_discrete.dropna(subset=feature_cols).reset_index(drop=True)
valid_indices = df_discrete_valid.index
# 接下来,将有效样本的离散型数据转换为数值:
# 使用一个简单规则:映射描述性字符串还原为数字,"Window_Scaling_cs" 或其他描述中的肯定部分 → 1,
# 而否定字符串(通常含 "no_") → 0.
def discrete_to_num(x):
if isinstance(x, str):
if "no_" in x:
return 0.0
else:
return 1.0
else:
return np.nan
for col in feature_cols:
df_discrete_valid[col] = df_discrete_valid[col].apply(discrete_to_num)
# 现在 df_discrete_valid 中的离散列已经转换为数值(1.0 或 0.0)。
############################################
# 3. 同步过滤原始数据并整合离散数据
############################################
# 对 df_total(原始完整数据)按 valid_indices 同步过滤,得到有效样本
df_total_valid = df_total.loc[valid_indices].copy()
# 将 df_total_valid 中原来存储离散型数据的对应列,替换为我们已经数值化的离散数据
for idx, col_name in zip(discrete_indices, feature_cols):
df_total_valid.iloc[:, idx] = df_discrete_valid[col_name]
# 此时 df_total_valid 的所有列均为数值型(离散列用 0/1 表示,其它列原样为 float,末尾有补的8个0)
# 同时,将标签同步过滤
total_labels_filtered = total_labels[valid_indices]
############################################
# 4. 对过滤后的数据进行归一化(min-max归一化)
############################################
# 转换 df_total_valid 为 numpy 数组,并确保为 float32
total_x_filtered = df_total_valid.to_numpy(dtype=np.float32)
X_min = np.min(total_x_filtered, axis=0)
X_max = np.max(total_x_filtered, axis=0)
X_range = X_max - X_min
X_range[X_range == 0] = 1
X_norm_filtered = (total_x_filtered - X_min) / X_range
# 输出结果检查
print("最终过滤后的数据形状:", X_norm_filtered.shape)
print("最终过滤后的标签形状:", total_labels_filtered.shape)
def data_prepross_as_string(filenames):
X, Y = [], []
for f in filenames:
print("Processing file:", f)
with open(os.path.join(os.getcwd(), f), 'r') as file:
# 假设需要跳过前253行头部信息
for line in file.readlines()[253:]:
# 保留“Y”或“N”,将 '?' 替换为 "0"
line = line.strip().replace('?', '0')
parts = line.split(',')
# 保留原始文本数据(离散部分不再转换为数值)
features = parts[:-1]
# 后面补充额外 8 个"0",与原来处理方式保持一致
features = features + ["0"] * 8
label = parts[-1].replace('FTP-CO0TROL', 'FTP-CONTROL').replace('I0TERACTIVE', 'INTERACTIVE')
label_idx = list_y.index(label)
X.append(features)
Y.append(label_idx)
X = np.array(X)
return X, np.array(Y)
请你帮我分析我上述代码属于哪种转化方式?
最新发布