固定缺失值处理看效果
先对之前的缺失值填充部分, 把效果不好的都弃用, 只留术式改为0/1特征. 用原来的填充方法跑一遍.
改值 # 术式(经典1背驮2)处理成术式(经典1背驮0) tabel_new.loc[:,'术式(经典1背驮2)'] = tabel.loc[:,'术式(经典1背驮2)'].replace(2,0) tabel=tabel_new.copy() |
改列名 # 改变列名 术式(经典1背驮2)->术式(经典1背驮0) all_data=all_data.rename(columns={'术式(经典1背驮2)':'术式(经典1背驮0)'}) |
(剩下的数据缺失值处理修改主要有: 删除各期尿量, 删除出院前归转几个特征, 修改术式的表示0/1)得到预测效果:
SVM/XGBoost/KNN F1对比(新目标TCA) | |||||||||
| 胸腔积液 | 凝血功能指标 | 转氨酶指标 | 胆红素指标 | 急性肺损伤 | 术后出血 | 术后感染 | 胆道并发症 | PNF(原发性移植肝无功能) |
SVM | 0.89 | 0.75 | 0.87 | 0.75 | 0.64 | 0.59 | 0.67 | 0.68 | 0.81 |
XGBoost | 0.90 | 0.81 | 0.83 | 0.71 | 0.49 | 0.40 | 0.20 | 0.25 | 0.10 |
KNN | 0.90 | 0.80 | 0.83 | 0.69 | 0.47 | 0.36 | 0.13 | 0.10 | 0.00 |
对比可看出KNN预测效果有明显提升.
HDA
然后修改降维模型TCA->HAD
用到learn_coding.py, learn_dictionary.py,HAD.py
修改两个工具包learn_coding.py, learn_dictionary.py的导入路径
多级目录导入, 参考:
https://www.cnblogs.com/kex1n/p/5971590.html
https://blog.csdn.net/qq_42393859/article/details/105682961
from data_process.HDA_utils import learn_coding from data_process.HDA_utils import learn_dictionary |
import learn_coding import learn_dictionary |
修改源域目标域数据读取路径:
Xs = pd.read_csv('../data/source_data.csv',index_col=0) Xt = pd.read_csv('../data/target_data.csv') Ys = pd.read_csv('../data/source_data_lable.csv') Yt = pd.read_csv('../data/target_data_lable.csv') |
Xs = pd.read_csv('./data/source_data.csv') Xt = pd.read_csv('./data/target_data.csv') Ys = pd.read_csv('./data/fill_labels.csv') Yt = Ys.copy(deep=True) |
修改保存路径
np.savetxt("HDA_s_data.csv", Ss, delimiter=',') np.savetxt("HDA_t_data.csv", St, delimiter=',') |
Ss.to_csv('./data/HDA_s_data.csv', index=False) St.to_csv('./data/HDA_t_data.csv', index=False) |
这个代码的缩进格式有点乱, 一会儿顶格, 一会儿def, 中间还夹杂着if __name__=='__main__':, 等做完这一波实验有空要检查重构一下.
计算W矩阵后一直在输出:
cand_feature: 2 add_feature 2 with neg sign No sign flips, not doing line search(没有符号反转, 不做线性搜索) |
考虑HAD可能没有起到作用
SVM预测
接下来用比较稳定的SVM进行预测
看了下HAD-SVM与TCA-SVM的代码基本相似, 所以将预测代码与TCA的SVM放在一块.
new_labels_HDA_SVM_cross_val_train(9) |
修改读入路径:
train_data = pd.read_csv('./data/TCA_source_data.csv') test_data = pd.read_csv('./data/TCA_target_data.csv') |
train_data = pd.read_csv('./data/HDA_s_data.csv') test_data = pd.read_csv('./data/HDA_t_data.csv') |
修改保存路径:
recall.to_csv('./data/1.7features_TCA+SVM_cross_val_recall.csv', index=False) f1.to_csv('./data/1.7features_TCA+SVM_cross_val_f1.csv', index=False) |
recall.to_csv('./data/1.7features_HDA+SVM_cross_val_recall.csv', index=False) f1.to_csv('./data/1.7features_HDA+SVM_cross_val_f1.csv', index=False) |
报错:
for train_index, test_index in skfolds.split(X, Y): |
Found input variables with inconsistent numbers of samples: [102, 850] |
打印下X,Y形状
shape of X:(102, 425) shape of Y:(850,) |
Y850是源域目标域拼接后导致样本量倍增
X经过HDA之后为什么样本量会变少呢, 看一下原版的HDA输出, 原版的预测标签名是写死的, 还不能直接用. 但读入数据的维度是没有问题的
(425, 51) (425, 51) (425, 7) (425, 7) |
但发现原来的HAD-SVM在读入数据后还进行了转置:
train_data=train_data.T test_data=test_data.T |
我把它加入HAD生成数据时一起处理:
Ss = pd.DataFrame(Ss.T) St = pd.DataFrame(St.T) |
PCA
看原先的PCA流程
用到两个文件, data_split.py包和pca_svm.py
和其他降维方法差不多, 只不过是把PCA和SVM放在同一个文件中了, 但逻辑其实没有过多耦合的地方.
其中数据的读取与TCA/HAD不同, 因为没有迁移, 所以读取的时候没有从保存好的源域目标域文件读, 而是根据所有需要的特征直接读取. 此处用到的特征和源域相同, 是第1.3.5.7天的, 并没有全部取.
然后调用data_split中的函数划分训练集测试集:
from sklearn.model_selection import train_test_split data, data_test = train_test_split(data, test_size=0.20, random_state=0) print(data.shape) print(data_test.shape) X = data.iloc[:,0:457] Y = data.iloc[:, 457:463] X_test = data_test.iloc[:, 0:457] Y_test = data_test.iloc[:, 457:463] |
但是这个包不能直接用了, 因为其中有drop保存csv时操作不当导致的冗余unnamed特征等操作, 现在得到的数据集已经没有unnamed特征了.
不过现在也用不着划分了, 因为之后用的是交叉验证, 只要注意在SVM用的时候直接读取, 而不要读取两个再拼接.
发现原代码划分完测试集训练集后, 只对训练集统一做了PCA和归一化, 然后又在SVM用所有的训练集做交叉验证, 测试集就没用着. (用到测试集的地方都注释掉了, 可能是用交叉验证后就没有使用了)
尝试新建一个单独做PCA的文件
此处所用特征量与原方法保持一致, 也都使用源域特征, 但是扩大样本量, 所用样本共同做PCA.
原核心代码就是一个归一化, 和一个PCA:
scaler = preprocessing.StandardScaler() X_data = scaler.fit_transform(X_data) X_data_pca = pca(X_data, 50).real |
修改数据读取路径
data = pd.read_csv('data\do_fill_na.csv') |
data = pd.read_csv('./data/source_data.csv') |
不单独调用划分处理, 用之前划分好的源域数据集(输入TCA之前的内容)
X,Y,X_test,y_test = spl.data_split(data) X_data = X[important_column] |
X_data = data |
添加降维后特征保存功能
X_data_pca = pd.DataFrame(X_data_pca) X_data_pca.to_csv('./data/PCA_data.csv', index=False) |
SVM预测
接下来用SVM进行预测
看了下HAD-SVM与TCA-SVM的代码基本相似, 所以将预测代码与TCA的SVM放在一块.
new_labels_PCA_SVM_cross_val_train(9) |
修改读入路径:
train_data = pd.read_csv('./data/HDA_s_data.csv') test_data = pd.read_csv('./data/HDA_t_data.csv') |
train_data = pd.read_csv('./data/PCA_data.csv') |
此处与TCA, HAD不同, 不必拼接源域目标域, 但目前代码拼接源域目标域, 并取对应任务目标的一列y值两个功能耦合在一起, 并在单个最底层的SVM训练预测函数中了, 尝试提出来
recall[i], f1[i]=train_SVM_cross_val(train_data_lable,test_data_lable,train_data,test_data,i) |
# 拼接源域目标域 data = np.vstack((train_data, test_data)) # Y = np.vstack((all_train_lable[y_columns[label_idx]], all_test_lable[y_columns[label_idx]])) label = np.vstack((train_data_lable, test_data_lable))recall[i], f1[i]=train_SVM_cross_val(data,label,i) def train_SVM_cross_val(X,all_lable,label_idx): Y = all_lable[y_columns[label_idx]] |
报错:
only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices |
大多数原因是因为 整型和浮点型造成的 比如Numpy在处理矩阵的时候,出现下标 17.0 和17 ,一般只有int 型可以做下标,所以需要强制类型int() |
因为之前是先取列, 在用np的拼接函数, 转换成数组, 现在是先转换成数组在取列, 就只能取整数了, 没有列名可以取, 并且用名字取的时候可以自动识别是行还是列, 此处要同时控制行列, 取所有行和特定列(否则默认取行).
修改label取列过程
Y = all_lable[:,label_idx] |
成功了, TCA准确率也没变, 接下来同理修改HAD的过程
recall[i], f1[i]=train_SVM_cross_val(train_data_lable,test_data_lable,train_data,test_data,i) |
# 拼接源域目标域 data = np.vstack((train_data, test_data)) label = np.vstack((train_data_lable, test_data_lable)) recall[i], f1[i]=train_SVM_cross_val(data,label,i) |
修改PCA参数
recall[i], f1[i]=train_SVM_cross_val(train_data,train_data_lable,i) |
修改保存路径:
recall.to_csv('./data/1.7features_TCA+SVM_cross_val_recall.csv', index=False) f1.to_csv('./data/1.7features_TCA+SVM_cross_val_f1.csv', index=False) |
recall.to_csv('./data/1.7features_PCA+SVM_cross_val_recall.csv', index=False) f1.to_csv('./data/1.7features_PCA+SVM_cross_val_f1.csv', index=False) |
报错:
(slice(None, None, None), 0)' is an invalid key |
考虑是没有经过拼接, 还是dataframe格式, 不能切片, dataframe转ndarray: .values
data=train_data.values label=train_data_lable.values recall[i], f1[i]=train_SVM_cross_val(data,label,i) |
成功得到结果
EF
记得上次胡老师说TCA之后50个特征对SVM已经够少了. 而之前EF选择重构特征将已经组合降维后的进行处理, 可能不如直接用原始特征重构效果好.
这次尝试EF后接TCA.
先修改读入数据路径:
data = pd.read_csv('./data/do_fill_na.csv') data.drop(['序列号','身高', 'Unnamed: 0.1', 'Unnamed: 0'], axis=1, inplace=True) X = data.iloc[:,0:456] Y = data.iloc[:, 456:463] |
X = pd.read_csv('./data/source_data.csv') Y = pd.read_csv('./data/fill_labels.csv') |
考虑到源域目标域的特征名称不同, 将他们分别做EF
因为有复用, 所以重构代码, 传入参数为此时的X和Y, 而划分训练集测试集的功能和调用EF的部分共同封装. 修改保存路径, 源域目标域分别保存, 保存的时候别忘了加, index=False
#源域特征重构 train_all_label_EF(source_data,source_data_lable,'EF_source_data') # 目标域特征重构 train_all_label_EF(target_data,target_data_lable,'EF_target_data') |
#拟合9个并发症目标 def train_all_label_EF(X,Y,data_name): # x_train=np.array(x_train) # x_test=np.array(x_test) # y_train=np.array(y_train) # y_test = np.array(y_test) X=np.array(X) Y=np.array(Y) for i in range(9): # train_EF(x_train,y_train,x_test,y_test,i) new_data=train_EF(X,Y,i) #保存新特征的数据 new_data = pd.DataFrame(new_data) new_data.to_csv('./data/{}_fity{}.csv'.format(data_name,i)) new_data.to_csv('./data/{}_fity{}.csv'.format(data_name,i), index=False print('{} new features saved'.format(i)) |
修改EF,返回所有构建结果
new_X = feature_append(r, X, list(code_importance_dict.keys())[:20], only_new_features=True) # 返回所有构建的新特征 return new_X |
之前是降到20维写死在程序里, 现在传入参数
new_X = feature_append(r, X, list(code_importance_dict.keys())[:dim], only_new_features=True) |
new_data=train_EF(X,Y,i,dim=200) |
EF+TCA
因为有多个目标, 所以还要循环读各个目标的特征重构数据集
修改读取/保存路径
for i in range(9): source_data = pd.read_csv('./data/{}_fity{}.csv'.format('EF_source_data',i)) target_data = pd.read_csv('./data/{}_fity{}.csv'.format('EF_target_data',i)) print("source_data.shape:",source_data.shape ) print("target_data.shape:",target_data.shape ) tca = TCA(kernel_type='rbf', dim=50, lamb=0.9, gamma=0.5) Xs_new, Xt_new = tca.fit(source_data, target_data) Xs_new = pd.DataFrame(Xs_new) Xt_new = pd.DataFrame(Xt_new) #print(Xs_new) # Xs_new.to_csv('./data/TCA_source_data.csv', index=False) # Xt_new.to_csv('./data/TCA_target_data.csv', index=False) Xs_new.to_csv('./data/{}_fity{}.csv'.format('TCA_after_EF_source_data',i), index=False) Xt_new.to_csv('./data/{}_fity{}.csv'.format('TCA_after_EF_target_data',i), index=False) |
这样的话之后SVM也要读多次, 考虑之后SVM如果读两个文件还是要拼接, 干脆这里拼接了再保存, 减少文件数量.
Xs_new = pd.DataFrame(Xs_new) Xt_new = pd.DataFrame(Xt_new) Xs_new.to_csv('./data/{}_fity{}.csv'.format('TCA_after_EF_source_data',i), index=False) Xt_new.to_csv('./data/{}_fity{}.csv'.format('TCA_after_EF_target_data',i), index=False) |
X_new = np.vstack((Xs_new, Xt_new)) X_new = pd.DataFrame(X_new) X_new.to_csv('./data/{}_fity{}.csv'.format('TCA_after_EF_data',i), index=False) |
报错, 维度不匹配
source_data.shape: (425, 200) target_data.shape: (425, 200) (425, 50) (425, 50) source_data.shape: (425, 200) target_data.shape: (425, 149) |
这个目标域的特征数量竟然少了, 是因为实在没有相关特征了吗, 查看所有EF文件, 确实都不一样多, 最少的约123个特征, 那就筛选到100个叭
new_data=train_EF(X,Y,i,dim=100) |
SVM
修改数据读取方式
def new_labels_EF_TCA_SVM_cross_val_train(label_num=9): train_data = pd.read_csv('./data/TCA_source_data.csv') test_data = pd.read_csv('./data/TCA_target_data.csv') # 拼接源域目标域 data = np.vstack((train_data, test_data)) |
data = pd.read_csv('./data/{}_fity{}.csv'.format('TCA_after_EF_data',i)) |
Data不拼接的时候记得转成ndarray
修改保存路径
recall.to_csv('./data/1.7features_EF+TCA+SVM_cross_val_recall.csv', index=False) f1.to_csv('./data/1.7features_EF+TCA+SVM_cross_val_f1.csv', index=False) |
各降维方法效果对比如下图
SVM/XGBoost/KNN F1对比(新目标TCA) | |||||||||
| 胸腔积液 | 凝血功能指标 | 转氨酶指标 | 胆红素指标 | 急性肺损伤 | 术后出血 | 术后感染 | 胆道并发症 | PNF(原发性移植肝无功能) |
TCA | 0.89 | 0.75 | 0.87 | 0.75 | 0.64 | 0.59 | 0.67 | 0.68 | 0.81 |
HDA | 0.86 | 0.73 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
PCA | 0.86 | 0.73 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
EF | 0.86 | 0.73 | 0.60 | 0.58 | 0.05 | 0.23 | 0.12 | 0.00 | 0.07 |