如何用Python为每个距离生成5条合成数据(优化LinearRegression代码)
问题描述
我有多份对应不同材料的CSV文件,每个文件包含两列数据:Distance(mm)和Counts,每个距离(从100mm到300mm,步长50mm)对应5条真实Counts数据(示例:100mm对应112、105、119、122、117;150mm对应89、84等)。我希望为每个材料的每个距离新增5条合成预测数据,使每个距离的数据量从5条增至10条,以提升实验报告的说服力。
目前针对某一材料的CSV编写了如下代码:
X_lead = lead.drop('counts', axis = 1) y_lead = lead['counts'] x_lead_train, x_lead_test, y_lead_train, y_lead_test = train_test_split(X_lead, y_lead, test_size=0.2, random_state=42 ) model = LinearRegression() model.fit(x_lead_train, y_lead_train) predictions = model.predict(x_lead_test) print(predictions) print(x_lead_train.shape, y_lead_train.shape) print(x_lead_test.shape, y_lead_test.shape)
运行输出:
[25.825 25.175 26.15 24.85 25.5 ] (20, 1) (20,) (5, 1) (5,)
运行后发现,代码仅生成了5条预测数据(对应5个距离各1条),但我需要每个距离生成5条合成数据,请问如何优化代码实现该需求?我已将所有CSV加载为DataFrame,便于复用代码。
优化方案
核心思路是:针对每个距离的真实数据特征(均值、标准差),生成符合该组数据离散性的合成数据,同时可结合回归模型保留距离与Counts的整体趋势。
步骤1:分析每组数据的统计特征
先按Distance(mm)分组,计算每组真实Counts的均值和标准差,这是生成合理合成数据的基础:
import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression # 按距离分组,统计每组的均值和标准差 group_stats = lead.groupby('Distance(mm)')['Counts'].agg(['mean', 'std']).reset_index()
步骤2:生成合成数据
提供两种可选方案,可根据需求选择:
方案A:基于分组统计特征生成(简单高效)
直接利用每组真实数据的均值和标准差,生成服从正态分布的合成数据,模拟真实数据的离散性:
synthetic_data = [] for _, row in group_stats.iterrows(): distance = row['Distance(mm)'] # 用该组真实数据的均值和标准差生成合成值 synthetic_counts = np.random.normal(loc=row['mean'], scale=row['std'], size=5) # Counts为整数,按需取整 synthetic_counts = synthetic_counts.round().astype(int) # 将数据存入列表 for count in synthetic_counts: synthetic_data.append({'Distance(mm)': distance, 'Counts': count}) # 转换为DataFrame synthetic_df = pd.DataFrame(synthetic_data)
方案B:基于回归模型+噪声生成(保留距离趋势)
如果希望合成数据既符合距离与Counts的整体关联趋势,又保留每组的离散性,可先训练全局回归模型,再在预测值基础上加入对应组的噪声:
# 训练全局线性回归模型 X = lead[['Distance(mm)']] y = lead['Counts'] model = LinearRegression() model.fit(X, y) synthetic_data = [] for _, row in group_stats.iterrows(): distance = row['Distance(mm)'] # 用模型预测该距离的基准值 base_pred = model.predict([[distance]])[0] # 使用该组真实数据的标准差作为噪声尺度 synthetic_counts = np.random.normal(loc=base_pred, scale=row['std'], size=5) synthetic_counts = synthetic_counts.round().astype(int) # 将数据存入列表 for count in synthetic_counts: synthetic_data.append({'Distance(mm)': distance, 'Counts': count}) synthetic_df = pd.DataFrame(synthetic_data)
步骤3:合并真实与合成数据
将原始数据与合成数据合并,得到每个距离下10条数据的最终结果:
final_df = pd.concat([lead, synthetic_df], ignore_index=True) # 按距离排序,方便查看 final_df = final_df.sort_values('Distance(mm)').reset_index(drop=True)
步骤4:批量处理所有材料
封装成函数,批量处理多个材料的DataFrame:
def generate_synthetic_data(df): group_stats = df.groupby('Distance(mm)')['Counts'].agg(['mean', 'std']).reset_index() # 训练全局模型(方案B用,方案A可注释掉以下两行) X = df[['Distance(mm)']] y = df['Counts'] model = LinearRegression() model.fit(X, y) synthetic_data = [] for _, row in group_stats.iterrows(): distance = row['Distance(mm)'] # 方案A替换为:base_val = row['mean'] base_val = model.predict([[distance]])[0] synthetic_counts = np.random.normal(loc=base_val, scale=row['std'], size=5) synthetic_counts = synthetic_counts.round().astype(int) for count in synthetic_counts: synthetic_data.append({'Distance(mm)': distance, 'Counts': count}) synthetic_df = pd.DataFrame(synthetic_data) final_df = pd.concat([df, synthetic_df], ignore_index=True).sort_values('Distance(mm)').reset_index(drop=True) return final_df # 假设所有材料的DataFrame存储在字典中,例如:material_dfs = {'lead': lead_df, 'copper': copper_df} for material_name, df in material_dfs.items(): final_df = generate_synthetic_data(df) # 保存为新的CSV文件 final_df.to_csv(f'{material_name}_with_synthetic.csv', index=False)
内容的提问来源于stack exchange,提问作者Cocoapod
相关产品推荐
相关产品推荐

