eval和ast.literal_val()

本文深入探讨了Python中eval函数的功能,解释了其如何将字符串转换为数据类型,并介绍了其潜在的安全风险。同时,对比了ast.literal_eval的使用场景,强调了其安全性,适合于需要解析未知内容但又希望避免安全威胁的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

eval函数的作用是把数据还原成它本身或者是能够转化成的数据类型。

eval在做计算前并不知道需要转化的内容是不是合法的(安全的)python数据类型。

使用eval可以实现从元祖,列表,字典型的字符串到元祖,列表,字典的转换,此外,eval还可以对字符串型的输入直接计算。

ast.literal则会判断需要计算的内容计算后是不是合法的python类型,如果是则进行运算,否则就不进行运算。

如何调用tensorflow训练完的模型# 导入必要的库 import os # 用于文件目录操作 import ast # 用于解析字符串形式的Python数据结构 import numpy as np # 用于数值计算 import tensorflow as tf # 深度学习框架 import matplotlib # 用于数据可视化 # 强制设置后端为'Agg'(非交互式,适合服务器环境保存图片) matplotlib.use('Agg') import sklearn # 导入机器学习工具库 # 强制使用CPU,禁用GPU加速(如果需要GPU加速可移除这些代码) os.environ["CUDA_VISIBLE_DEVICES"] = "-1" # 设置环境变量,指定不可用的GPU设备 tf.config.set_visible_devices([], "GPU") # 显式设置不可用的GPU设备 # 关键修改:禁用分布式检测(适用于TensorFlow 2.19.0版本) import tensorflow.python.keras.engine.data_adapter as data_adapter # 导入数据适配器模块 def is_distributed_dataset_patch(ds): return False # 强制返回非分布式数据集,解决某些版本的兼容性问题 data_adapter._is_distributed_dataset = is_distributed_dataset_patch # 替换原有函数 # 从Keras导入模型层相关组件 from keras.models import Sequential # 导入顺序模型 from keras.layers import Dense, Dropout # 导入全连接层Dropout层 from keras.callbacks import EarlyStopping # 导入早停回调函数 from sklearn.model_selection import train_test_split # 导入数据划分函数 from sklearn.preprocessing import StandardScaler # 导入数据标准化工具 import matplotlib.pyplot as plt # 导入绘图模块 # 设置中文字体,确保中文能正常显示 plt.rcParams["font.family"] = ["SimHei"] # 使用黑体 plt.rcParams["axes.unicode_minus"] = False # 正确显示负号 # 数据处理函数定义 def process_data(file_path): """处理单个数据文件,提取前19列最后一列""" with open(file_path, 'r', encoding='utf-8') as file: file_content = file.read() # 读取文件内容 file_content = ''.join(file_content.split('\n')) # 移除换行符 file_content = file_content.replace(' ', '') # 移除多余空格 try: data = ast.literal_eval(file_content) # 解析字符串为Python数据结构 except Exception as e: print(f"解析数据时出错 ({file_path}): {e}") # 打印错误信息 return None, None # 解析失败返回None first_19_columns = [] # 存储前19列数据 last_column = [] # 存储最后一列数据 for row in data: first_19 = row[:19] # 提取前19个元素 first_19_columns.append(first_19) # 添加到列表 last = row[-1] # 提取最后一个元素 last_column.append(last) # 添加到列表 first_19_array = np.array(first_19_columns) # 转换为NumPy数组 last_column_array = np.array(last_column) # 转换为NumPy数组 return first_19_array, last_column_array # 返回处理后的数据 def process_multiple_files(file_paths): """处理多个数据文件,合并所有文件的数据""" all_first_19 = [] # 存储所有文件的前19列数据 all_last_col = [] # 存储所有文件的最后一列数据 for file_path in file_paths: first_19, last_col = process_data(file_path) # 处理单个文件 if first_19 is not None and last_col is not None: print(f"成功处理文件: {file_path}") # 打印成功信息 all_first_19.append(first_19) # 添加到列表 all_last_col.append(last_col) # 添加到列表 if all_first_19: # 垂直堆叠数组(合并行)水平堆叠数组(合并列) combined_first_19 = np.vstack(all_first_19) combined_last_col = np.hstack(all_last_col) return combined_first_19, combined_last_col # 返回合并后的数据 else: print("没有成功处理任何文件") # 打印错误信息 return None, None # 没有成功处理任何文件返回None def get_txt_files_in_directory(directory): """获取指定目录下的所有txt文件路径""" if not os.path.exists(directory): print(f"错误:目录 {directory} 不存在") # 打印错误信息 return [] # 目录不存在返回空列表 # 生成目录下所有txt文件的完整路径 return [os.path.join(directory, f) for f in os.listdir(directory) if f.endswith('.txt') and os.path.isfile(os.path.join(directory, f))] # 模型构建函数 def build_neural_network(input_dim): """构建神经网络模型""" model = Sequential([ # 创建顺序模型 Dense(128, activation='relu', input_shape=(input_dim,)), # 输入层第一个隐藏层 Dropout(0.2), # 防止过拟合的Dropout层,随机丢弃20%的神经元 Dense(64, activation='relu'), # 第二个隐藏层 Dropout(0.2), # 防止过拟合的Dropout层 Dense(32, activation='relu'), # 第三个隐藏层 Dense(1) # 输出层,单个神经元用于回归预测 ]) model.compile( # 编译模型 optimizer='adam', # 使用Adam优化器 loss='mse', # 均方误差损失函数,适合回归问题 metrics=['mae'] # 平均绝对误差,评估预测准确性 ) return model # 返回构建好的模型 # 主函数,程序入口 def main(): # 自动获取目录下的所有txt文件 directory = r"D:\4_python_code\02_BP神经网络" # 设置数据目录路径 file_paths = get_txt_files_in_directory(directory) # 获取所有txt文件路径 if not file_paths: print(f"在目录 {directory} 中未找到txt文件") # 打印错误信息 return # 没有找到文件则退出 # 处理多个文件并获取合并数据 X, y = process_multiple_files(file_paths) # 处理数据 if X is None or y is None: print("没有可用的数据进行训练") # 打印错误信息 return # 没有可用数据则退出 print(f"合并后的数据形状 - 输入: {X.shape}, 输出: {y.shape}") # 打印数据形状 # 数据预处理 - 标准化输入特征 scaler = StandardScaler() # 创建标准化器 X_scaled = scaler.fit_transform(X) # 拟合数据并转换 # 划分训练集测试集 (80% 训练, 20% 测试) X_train, X_test, y_train, y_test = train_test_split( X_scaled, y, test_size=0.2, random_state=42 # 随机种子确保结果可复现 ) print(f"训练集形状: {X_train.shape}, {y_train.shape}") # 打印训练集形状 print(f"测试集形状: {X_test.shape}, {y_test.shape}") # 打印测试集形状 # 构建神经网络模型 model = build_neural_network(X.shape[1]) # 构建模型 model.summary() # 打印模型结构摘要 # 早停策略 - 防止过拟合 early_stopping = EarlyStopping( monitor='val_loss', # 监控验证损失 patience=10, # 连续10轮没有改善则停止 restore_best_weights=True # 恢复最佳权重 ) # 训练模型 history = model.fit( X_train, y_train, # 训练数据 epochs=100, # 最大训练轮次 batch_size=32, # 批次大小 validation_split=0.2, # 划分20%的训练数据作为验证集 callbacks=[early_stopping], # 早停回调 verbose=1 # 训练过程显示模式 ) # 评估模型 evaluation = model.evaluate(X_test, y_test) # 在测试集上评估模型 print(f"\n测试集评估 - 损失: {evaluation[0]}, MAE: {evaluation[1]}") # 打印评估结果 # 预测测试集 y_pred = model.predict(X_test).flatten() # 对测试集进行预测并展平结果 # 绘制训练过程(确保后端已设置) plt.figure(figsize=(12, 4)) # 创建绘图窗口 plt.subplot(1, 2, 1) # 创建第一个子图 plt.plot(history.history['loss'], label='训练损失') # 绘制训练损失 plt.plot(history.history['val_loss'], label='验证损失') # 绘制验证损失 plt.title('模型损失') # 设置标题 plt.xlabel('训练轮次') # 设置x轴标签 plt.ylabel('损失') # 设置y轴标签 plt.legend() # 显示图例 plt.subplot(1, 2, 2) # 创建第二个子图 plt.scatter(y_test, y_pred, alpha=0.5) # 绘制预测值与实际值的散点图 plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--') # 绘制对角线 plt.title('预测值 vs 实际值') # 设置标题 plt.xlabel('实际值') # 设置x轴标签 plt.ylabel('预测值') # 设置y轴标签 plt.tight_layout() # 自动调整子图间距 # 保存图片(非交互式后端需要显式保存) plt.savefig('training_results.png') # 保存训练结果图 # plt.show() # 非交互式后端不支持show(),如需显示可改用TkAgg后端 # 保存模型 model.save("neural_network_model.h5") # 保存模型到文件 print("模型已保存为 neural_network_model.h5") # 打印保存成功信息 print("训练结果图已保存为 training_results.png") # 打印保存成功信息 if __name__ == "__main__": main() # 调用主函数,启动程序如何调用训练好的模型预测
最新发布
05-30
帮我注释代码,并检查代码问题,我想得到空间解卷积之后的单细胞分辨率的可视化df = point_cell_count_pos df['cell_coord'] = df['cell_coord'].apply(ast.literal_eval) ## 对'cell_coord'列中的细胞坐标转换成列表类型 point_xy_cls_ori_proptofreq = [] ## 创建一个存储所有绘制图形的细胞的坐标,所在spot的该细胞类型的实际丰度,细胞类型,所在spot的barcode,所在spot实际画的细胞数,所在spot的细胞数 ct_Freq_allbc=pd.DataFrame(columns=celltype_Frequency_c2l.columns) ## 转换后的每个spot细胞丰度,未过滤 for bc in df.index: xy_ori_coord = df.loc[bc, "cell_coord"] # 获取该spot的所有细胞坐标列表 num = len(xy_ori_coord) if num == 0: continue bcneighbors = bc.split("_") # 得到所有邻居spot的barcode ctfreqidx = celltype_Frequency_c2l.index.isin(bcneighbors) ## 检查所有邻居spot是否在组织区域, if sum(ctfreqidx) == len(bcneighbors): ## 所有邻居spot都在组织区域,或者该spot本来就在组织区域 # 提取所有邻近spot的cell2location解卷积结果,逐列取平均,作为该spot的解卷积结果 allctfreq_bc = pd.DataFrame(celltype_Frequency_c2l.loc[ctfreqidx, :].mean(axis=0)).T elif sum(ctfreqidx) > 0: # 部分邻居spot在组织区域,按列求,再除于邻居spot的个数 ct = list(celltype_Frequency_c2l.index[ctfreqidx].values) allctfreq_bc = pd.DataFrame(celltype_Frequency_c2l.loc[ct, :].sum(axis=0) / len(bcneighbors)).T else: continue ############方法一: # 计算该spot的每一种细胞类型的丰度占比 allctprop_bc = allctfreq_bc.div(allctfreq_bc.sum(axis=1), axis=0) # 转换成丰度的占比之后,把spot的细胞核识别细胞数量与占比相乘得到实际的丰度 allctprop_bc = allctprop_bc.apply(lambda x: x * num, axis=1) ct_Freq_allbc.loc[bc] = allctprop_bc.loc[0] ## 保存转换后的丰度矩阵 celltype_Proptofreq_bc = [] filterctProptofreq_bc = [] # 过滤掉的细胞类型 for cls in celltype_Frequency_c2l.columns: real_cell_freq = allctprop_bc.at[0,cls] # 使用细胞丰度的阈值进行过滤 if real_cell_freq >= ctfreq_threshold: celltype_Proptofreq_bc.append([real_cell_freq,cls, bc]) else: filterctProptofreq_bc.append([real_cell_freq,cls, bc]) celltype_Proptofreq_bc.sort(key=lambda x: x[0]) ## 排序 filterctProptofreq_bc.sort(key=lambda x: x[0], reverse=True) ## 低于阈值的细胞类型,从高到低排序 point = num ## 剩余的细胞数 bcplotpoint = 0 ## 已经分配好身份的细胞数 candidate = list(range(num)) # 可选择的点索引 for celltypefreq,celltype,_ in celltype_Proptofreq_bc: if point <= 0: break vis_point = math.ceil(celltypefreq) ## 向上取整,得到该细胞类型的细胞丰度画的细胞数 celltype_vis_point = min(vis_point, point) ## 实际画的细胞数,不会超过剩余的细胞数 selected = np.random.choice(candidate, celltype_vis_point, replace=False) for s in selected: x, y = xy_ori_coord[s] ## 提取坐标 point_xy_cls_ori_proptofreq.append([x,y,celltypefreq,celltype,bc,celltype_vis_point,num]) ## 分配细胞类型标签 point -= celltype_vis_point bcplotpoint += celltype_vis_point candidate = list(set(candidate) - set(selected)) # 20240913修改15:00 # 只考虑了应该画出来的细胞类型实际丰度大于剩余细胞数的情况, # 但是我们可能少考虑了小于剩余细胞数的情况 # 就是如果细胞类型很少了,他的丰度也不高,少于剩余细胞数,然后就会丢失一部分细胞,没有身份也就不会被画出来 # 对没有身份这部分细胞进行填补,把没有分配到身份的细胞分配一个丰度最高的过滤掉的细胞类型,按顺序填完 if bcplotpoint < num: notagpoint = num - bcplotpoint ## 剩余的未分配身份的细胞数 for ftcelltypefreq,ftcelltype,_ in filterctProptofreq_bc: if notagpoint <= 0: break ftvis_point = math.ceil(ftcelltypefreq) ## 向上取整,得到该细胞类型的细胞丰度画的细胞数 ftcelltype_vis_point = min(ftvis_point, notagpoint) ## 实际画的细胞数,不会超过剩余未分配身份的细胞数 ftselected = np.random.choice(candidate, ftcelltype_vis_point, replace=False) for z in ftselected: x, y = xy_ori_coord[z] point_xy_cls_ori_proptofreq.append([x,y,ftcelltypefreq,ftcelltype,bc,ftcelltype_vis_point,num]) notagpoint -= ftcelltype_vis_point candidate = list(set(candidate) - set(ftselected))
03-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值