第一次任务是将datawhale提供的baseline在飞桨平台上跑通,这也是我第一次在平台上跑项目,相对来说还是比较顺利的,下述是自己新学习到的、规范的代码的记录。
import glob # 获取文件路径
import numpy as np
import pandas as pd
import nibabel as nib # 处理医学图像数据
from nibabel.viewers import OrthoSlicer3D # 图像可视化
from collections import Counter # 计数统计
其中glob文件处理以及collection是之前没有使用过的,我先特别注意到了这两个module在后续的使用。
def extract_feature(path):
# 加载PET图像数据
img = nib.load(path)
# 获取第一个通道的数据
img = img.dataobj[:, :, :, 0]
# 随机筛选其中的10个通道提取特征
random_img = img[:, :, np.random.choice(range(img.shape[2]), 10)]
# 对图片计算统计值
feat = [
(random_img != 0).sum(), # 非零像素的数量
(random_img == 0).sum(), # 零像素的数量
random_img.mean(), # 平均值
random_img.std(), # 标准差
len(np.where(random_img.mean(0))[0]), # 在列方向上平均值不为零的数量
len(np.where(random_img.mean(1))[0]), # 在行方向上平均值不为零的数量
random_img.mean(0).max(), # 列方向上的最大平均值
random_img.mean(1).max() # 行方向上的最大平均值
]
# 根据路径判断样本类别('NC'表示正常,'MCI'表示异常)
if 'NC' in path:
return feat + ['NC']
else:
return feat + ['MCI']
这部分可以在其他的影像中也可以去套用,提取基础的数值(同时也可以筛选离群的值以免模型的偏离)
from sklearn.linear_model import LogisticRegression
m = LogisticRegression(penalty='l2',dual=False,C=1.0,n_jobs=1,random_state=20,max_iter=1000)
m.fit(
np.array(train_feat)[:, :-1].astype(np.float32), # 特征
np.array(train_feat)[:, -1] # 类别
)
其中sklearn中有许多其他的模型,诸如
import sklearn.linear_model as sk_linear
model = sk_linear.LinearRegression(fit_intercept=True,normalize=False,copy_X=True,n_jobs=1)
model = sk_linear.LogisticRegression(penalty='l2',dual=False,C=1.0,n_jobs=1,random_state=20,fit_intercept=True) #逻辑斯蒂回归
model = sk_bayes.MultinomialNB(alpha=1.0,fit_prior=True,class_prior=None) #多项式分布的朴素贝叶斯
model = sk_bayes.BernoulliNB(alpha=1.0,binarize=0.0,fit_prior=True,class_prior=None) #伯努利分布的朴素贝叶斯
model = sk_bayes.GaussianNB()#高斯分布的朴素贝叶斯
model = sk_tree.DecisionTreeClassifier(criterion='entropy',max_depth=None,min_samples_split=2,min_samples_leaf=1,max_features=None,max_leaf_nodes=None,min_impurity_decrease=0) #决策树
model = sk_svm.SVC(C=1.0,kernel='rbf',gamma='auto') #SVM
通过对训练集合的真实标签和预测结果进行对比,计算accuracy,f1-score等评判标准
import time
import numpy as np
from sklearn.metrics import precision_recall_fscore_support
from sklearn.metrics import accuracy_score
train_pred = m.predict(np.array(train_feat)[:, :-1].astype(np.float32))
y_pred=train_pred
y_true=np.array(train_feat)[:, -1]
result = precision_recall_fscore_support(y_true, y_pred, average='macro')
print(result)
acc = accuracy_score(y_true, y_pred)
print(acc)
实际上训练集合的效果未必能是真正意义上的“好”,可能存在对训练集合的过拟合,而对实际数据产生较差的结果,所以交叉验证是很必要的
交叉验证也是一个重要的思想,防止过拟合(具体的信息可参考知乎文档:【机器学习】Cross-Validation(交叉验证)详解 - 知乎 (zhihu.com))
import sklearn.model_selection as sk_model_selection
accs=sk_model_selection.cross_val_score(model, iris_X, y=iris_y, scoring=None,cv=10, n_jobs=1)
print('交叉验证结果:',accs)
或者以另外一种方法
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
#创建一个管道(Pipeline)实例,里面包含标准化方法和随机森林模型
pipeline = make_pipeline(StandardScaler(), RandomForestClassifier(n_estimators=100, max_depth=4))
# 创建一个用于得到不同训练集和测试集样本的索引的StratifiedKFold实例,折数为10
strtfdKFold = StratifiedKFold(n_splits=10)
#把特征和标签传递给StratifiedKFold实例
kfold = strtfdKFold.split(train_X, train_Y)
#循环迭代,(K-1)份用于训练,1份用于验证,把每次模型的性能记录下来。
scores = []
for k, (train, test) in enumerate(kfold):
pipeline.fit(train_X, train_Y)
score = pipeline.score(train_X, train_Y)
scores.append(score)
print('\n\nCross-Validation accuracy: %.3f +/- %.3f' %(np.mean(scores), np.std(scores)))