IP地址数据集单变量PDF计算与绘图异常问题排查
问题分析:IP数据集PDF计算与绘图异常排查
我有两个各包含10k个整数编码IP地址的数据集,一个是真实网络捕获数据,另一个是AI生成的合成数据。为对比二者分布差异,我尝试计算单变量概率密度函数(PDF),但计算和绘图过程中出现异常。
用户原始代码
数据预处理代码
import numpy as np import pandas as pd q=np.array(real_data_1m.srcip) p=np.array(syn_data_1m.srcip) #get all possible discrete events from p and q px=np.array(list(set(p))) #use set here to remove duplicates qx=np.array(list(set(q))) #use set here to remove duplicates #concatenate px and qx mx=np.concatenate([px,qx]) mx.sort() #sort them, as they are anyway integers mx=np.array(list(set(mx))) #remove duplicates by creating a set #mx.reshape((len(mx),1)) #reshape from 1D to nD, where n=len(mx)
概率分布计算函数
def create_prob_dist(data: np.array, sample_space: np.array): #number of all events sum_of_events = sample_space.size #get the counts of each event via pandas.crosstab() data_counts = pd.crosstab(index='counts', columns=data) #create probabilities for each event prob_dist=dict() for i in sample_space: if i in data_counts: prob_dist[i]=(data_counts[i]['counts'])/sum_of_events else: prob_dist[i]=0 return prob_dist
绘图代码
#create true PDFs of p and q using mx p_pdf=create_prob_dist(p, mx) q_pdf=create_prob_dist(q, mx) #get the probability values only from the dictionary p_pdf=np.array(list(p_pdf.values())) #already sorted according to mx q_pdf=np.array(list(q_pdf.values())) #already sorted according to mx plt.figure() plt.plot(mx, q_pdf, 'g', label="Q") plt.plot(mx, p_pdf, 'r', label="P") plt.legend(loc="upper right") plt.show()
核心问题分析
- 概率计算逻辑错误:
- 用
sample_space.size(所有唯一IP的数量)作为分母计算概率是错误的。离散概率的正确计算方式是每个IP的出现次数 / 数据集总样本数(即10k),错误的分母会导致概率值被严重缩放,完全偏离真实分布。
- 用
pd.crosstab使用不当:pd.crosstab(index='counts', columns=data)生成的DataFrame结构不符合预期,后续索引查找容易出错。更高效可靠的方式是用np.unique(data, return_counts=True)直接获取唯一值和对应计数。
- 绘图方式不匹配离散IP分布:
- IP是离散且跨度极大的整数,用
plt.plot绘制折线图时,大量零概率IP会导致图像出现密集的垂直跳跃线,无法直观展示分布特征。
- IP是离散且跨度极大的整数,用
修正后的代码实现
1. 修正概率计算函数
def create_prob_dist(data: np.array): # 获取唯一IP及对应出现次数 unique_ips, counts = np.unique(data, return_counts=True) # 计算真实概率:次数 / 总样本数 probs = counts / len(data) return dict(zip(unique_ips, probs))
2. 生成对齐的概率数组(用于绘图)
# 获取所有唯一IP的联合样本空间并排序 all_ips = np.sort(np.unique(np.concatenate([p, q]))) # 生成真实数据的概率数组(缺失IP补0) q_probs = np.array([create_prob_dist(q).get(ip, 0) for ip in all_ips]) # 生成合成数据的概率数组(缺失IP补0) p_probs = np.array([create_prob_dist(p).get(ip, 0) for ip in all_ips])
3. 更合适的绘图方式
方式一:直方图(直观展示频率分布)
import matplotlib.pyplot as plt plt.figure(figsize=(12, 6)) # 真实数据直方图(density=True转为概率密度) plt.hist(q, bins=50, alpha=0.5, label="真实数据", density=True) # 合成数据直方图 plt.hist(p, bins=50, alpha=0.5, label="合成数据", density=True) plt.xlabel("整数编码IP") plt.ylabel("概率密度") plt.legend() plt.show()
方式二:核密度估计(KDE,平滑展示分布趋势)
from scipy.stats import gaussian_kde plt.figure(figsize=(12, 6)) # 真实数据KDE曲线 kde_q = gaussian_kde(q) xvals = np.linspace(min(all_ips), max(all_ips), 1000) plt.plot(xvals, kde_q(xvals), 'g', label="真实数据") # 合成数据KDE曲线 kde_p = gaussian_kde(p) plt.plot(xvals, kde_p(xvals), 'r', label="合成数据") plt.xlabel("整数编码IP") plt.ylabel("概率密度") plt.legend() plt.show()
可选:离散PDF散点图(过滤零概率值)
如果坚持展示离散概率分布,需过滤掉零概率IP避免图像混乱:
# 过滤真实数据的非零概率IP non_zero_mask_q = q_probs > 0 filtered_ips_q = all_ips[non_zero_mask_q] filtered_probs_q = q_probs[non_zero_mask_q] # 过滤合成数据的非零概率IP non_zero_mask_p = p_probs > 0 filtered_ips_p = all_ips[non_zero_mask_p] filtered_probs_p = p_probs[non_zero_mask_p] plt.figure(figsize=(12, 6)) plt.scatter(filtered_ips_q, filtered_probs_q, c='g', label="真实数据", s=5) plt.scatter(filtered_ips_p, filtered_probs_p, c='r', label="合成数据", s=5) plt.xlabel("整数编码IP") plt.ylabel("概率") plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者cs.lev
相关产品推荐
相关产品推荐

