前言

1.论文主体分为两个部分,域适应和置信学习,两者交替训练,逐步增加高置信度目标样本。域适应中cdd损失利用差异矩阵A,Amn = pm1pn2为C1将样本划分为m类和C2将样本划分为n类的概率之积,特征提取器通过最小化分类器差异来更新,而双分类器则通过最大化该差异来优化。
2.置信学习部分有两个输入,有噪声的伪标签Y(戴帽)和预测概率P(戴帽)。采用经过源数据训练的SVM分类器估计目标样本xt的预测概率 P(戴帽),伪标签Y由两个分类器结果相加得到,根据P和Y得到size为nt
k的计数矩阵C,C[i][j]为伪标签为i,真实标签为j的目标域样本数量。
3.而上一步咋判断样本数量呢?根据阈值tj,tj等于伪标签为j的所有目标域样本的SVM概率平均值。伪标签为i,对应SVM概率最大的为j且概率大于阈值tj。
4.对计数矩阵C归一化得到Q。然后采用PBC方法,对每个类{1……K},对伪标签为 i(1……K) 的样本根据自信度 p(y=i) 进行排序,选择nt*(求和j!=i的Q[i][j])个低置信度样本进行丢弃(这里我估计是总的,还需要看完代码深刻理解)。

Introduction

CLDA提出了一种新的框架,将域适应与置信学习相结合,前者减少域间差异并生成目标实例的伪标签,后者从中选择高置信度的目标样本。交替训练领域适应部分和置信学习部分,逐步提高目标领域中高置信度标签的比例,从而进一步提高分类的准确性。

为了评估标签质量,研究了一种称为置信学习(CL)[43]的方法,基于对噪声数据进行剪除的原理,采用概率阈值估计噪声,并对样本进行置信度训练。受置信学习的启发,我们根据目标数据的伪标签的置信度进行排序,以去除噪声伪标签。
本文框架的目标是使**用目标领域的高质量标记实例来训练深度神经网络。**通过使用自信学习来标记目标实例,从而将目标数据作为源数据应用于交叉熵损失函数的优化。
本文贡献:
算法贡献1)采用训练域适应与自信学习迭代交替的策略,优先训练高置信度标签的目标样本,可逐步增加目标域高置信度标签的比例,提高分类准确率。2)对于具有高置信度标签的目标实例,同时进行交叉熵损失和熵正则化损失,提高了目标域特征的判别能力。

CLDA


双分类器(C1和C2)输出两个概率向量p1和p2 (p1, p2∈R K ×1)来优化损失函数并更新神经网络,其中K为类别数。**特征融合分类以两个分类器的最后一层特征(softmax之前)为输入,选择两个特征之和中最大的元素作为伪标签[44]。**结果,得到了所有目标实例的伪标签Y(戴帽) = {yi}nt i=1。
置信学习用于修剪标记数据集上的噪声数据,并保留干净的数据用于模型训练。1)采用SVM分类器来估计预测概率 P。2) P 结合之前特征融合得到的目标样本伪标签 Y,这样就得到了可信联合矩阵C y,yt∈R K×K,将C y,yt归一化,yt可以得到联合分布矩阵Q y,yt∈RK×K. 3)具有高置信度的伪标签称为可信标签,nc为可信样本的个数。类权值w_confident_class∈RK用于更新神经网络时对实例进行加权。

algorithm

CLDA方法包括两个主要部分:领域适应和自信学习。域适应技术用于调整源域和目标域。自信学习尝试评估伪标签,从而选择具有高置信度的标签。将这些标签及其对应的样本作为目标域的一个新的训练集,并将其输入到域适应部分。通过在训练域适应和自信学习之间的迭代交替,CLDA方法可以逐步提高分类精度。
取C1和C2的最后一层特征(不带softmax),并通过求和的方式融合这两个特征。然后选择融合特征之后最大元素对应的类别作为样本伪标签。
图1右侧,自信学习尝试评估伪标签Y(戴帽),并从中选择自信标签Yc(戴帽),数量为nc。引入SVM分类器来获得目标域样本的预测概率(戴帽)P。**计数矩阵Cy,yt由P和Y得到,计算每个类别中属于这个类的具有足够大概率的样本的数量。**然后,C y,yt经过归一化得到Q y,yt,用来评估伪标签。通过剪枝操作,将伪标签分为可信标签和不可信标签。然后选择具有自信标签的目标样本作为域适应部分的训练数据。

域适应

通过特征提取器E与分类器C1和C2之间的对抗性学习[41]进行优化。具体来讲,特征提取器通过最小化分类器差异来更新,而双分类器则通过最大化该差异来优化。我们使用分类器确定性差异(CDD)来度量分类器差异。通过这种对抗性学习,分类域适应部分可以使源域和目标域的分布保持一致。CLDA方法的损失函数定义为

其中第一项表示标记源域样本上的分类损失,第二项表示未标记目标域样本上的CDD损失,第三项表示有自信标签的目标域样本上的分类损失,第四项表示目标域样本上的熵正则化[40],[45]损失。
1)最小化源分类损失:(两个分类器)

2)CDD损失
CDD损失将分类器C1和C2差异表述为不同目标域预测的类相关性;同时,对目标特征的可辨识性进行了隐式约束。
冻结E的参数,并通过最大化两个分类器之间的差异Lt d更新C1和C2(在这里最大化Lccd就是最大化C1和C2的差异)。定义如下:

A是预测相关性矩阵,用于表示分类器之间的差异。Amn = pm1*pn2为C1将样本划分为m类和C2将样本划分为n类的概率之积。通过对抗性优化CDD损失,同时增强了分类器的确定性和预测多样性。这样也减少了域间的差异。
3)目标分类损失:当目标域样本有自信标签时,使用自信标签进一步提高模型的分类精度。设Lt cls为有自信标签的目标域的分类损失,可表示为:

交叉熵损失的权重设置为w confident_class。
4)熵正则化:自信学习得到的目标域样本标签可能不准确,因此,通过对目标域样本[43]的**预测概率的约束,保证了类之间的低密度分离(这里我理解为将类与类之间的距离拉大,类内样本的距离变小,使得同一类的样本更聚集)。**对于目标域的概率预测结果,期望概率预测输出具有峰值分布,而不是平滑分布。

pki是目标域中两个分类器预测的概率的平均值

置信学习

confident learning需要两个输入,噪声伪标签Y(戴帽)和预测概率P(戴帽)。采用SVM分类器(经过源数据训练)估计目标样本的预测概率 P(戴帽)。
置信学习的过程可以分为两个步骤:1)估计伪标签 Y(戴帽)和真标签(未知,用 P估计)的联合分布矩阵Q y,yt,然后估计伪标签 Y(戴帽)的置信度;2)根据其置信度发现并剪除不可信标签。
首先,从Y(戴帽)和P(戴帽)中得到一个可信联合矩阵C y,yt来划分和计数标签误差。对于目标域,Xt( (戴帽)y=i,yt=j)表示具有伪标签 i 的样本xt,实际上具有真实标签 j。(戴帽) Xt(y=i,yt=j)用于估计 Xt( y=i, yt=j),表示Xt 标记为y=i 的样本集,是否具有足够的预测类别为 j 的概率 p(y=j;xt) 是由阈值tj 决定的。 tj 是每个类的阈值,等价于每个伪标签类的SVM概率的平均值。自动阈值方法使置信学习对类不平衡和异构类概率分布具有鲁棒性。因此,可信联合矩阵可以定义为:
注: ** (戴帽) Xt(y=i,yt=j) 表示伪标签为 i 的样本中svm概率>=阈值tj 的样本个数;C y,yt[i] [j]表示 (戴帽)Xt(y=i,yt=j) 的样本个数 **

将C y,yt归一化,得到联合分布矩阵Q y,yt的估计:

根据Q y,yt的估计,采用PBC(prune by class) 方法[43]对目标伪标签进行清理。对于每个类i∈{1,…K},我们首先对伪标签为 i 的样本根据自信度 (戴帽)p((戴帽)y=i;xt) 进行排序;然后选择 个自信度最低的例子 p(y=i;Xt) 作为不受信任的标签,并修剪它们。这样就得到了可信标签Yc∈Y。

**可信标签和样本{Xtc, (戴帽)Yc}被输入到特征提取器E中以替换所有目标域样本Xt,**并使用类权重w_confident_class对每个类中的目标监督损失函数进行重加权。

Implement Details

1)对于γ,测试了五个不同的值(0.001,0.005,0.01,0.05和0.1),α和β等于零。当γ = 0.01时,分类精度较高。2)对于α,测试了5个不同的值(0.01,0.05,0.1,0.5和1),γ等于0.01,β等于0。当α等于0.1时,结果更高。3)对于β,测试了5个不同的值(0.005,0.01,0.05,0.1和0.5),其中γ等于0.01,α等于0.1。当β = 0.01时,结果较高。
train_num=20

将领域适应的对抗性训练过程分为三个步骤。1) 首先,利用标记后的源域样本更新特征提取器(E)和两个分类器(C1和C2),提高了网络对源域样本的识别能力;
2) 当目标域有自信标签时,加入交叉熵损失和熵正则化损失,使网络对目标域样本的判别能力更强。可以表示为:

在自信学习开始前α = β = 0。其次,利用目标域样本更新分类器使得两个分类器差异最大化并保持源域样本的准确性,得到公式:

3)第三,使用未标记的目标域样本更新特征提取器,可表示为:使用自信样本将两个分类器差异最小化,对抗性优化

注意:利用自信学习找到更准确的带有自信标签的目标域样本,进一步监督分类器的训练,提高模型的可迁移性。
归一化C y,yt,得到联合分布矩阵Q y,yt。Q y,yt可以计算类权值过滤掉不可信的标签,为下一阶段的训练获取可信标签。

代码

## CLDA_UP2PC
num_epoch = args.epochs
num_k = args.num_k
BATCH_SIZE = args.batch_size
HalfWidth = 2
n_outputs = 128
nBand = 102
patch_size = 2 * HalfWidth + 1
CLASS_NUM = 7#load data
data_path_s = '/home/wbl/Dataset/HSI datasets/Pavia/paviaU.mat'
label_path_s = '/home/wbl/Dataset/HSI datasets/Pavia/paviaU_gt_7.mat'
data_path_t = '/home/wbl/Dataset/HSI datasets/Pavia/pavia.mat'
label_path_t = '/home/wbl/Dataset/HSI datasets/Pavia/pavia_gt_7.mat'
# 返回数据和标签 [610,340,102];[610,340]
source_data,source_label = load_data(data_path_s,label_path_s)
# [1096,715,102];[1096,715]
target_data,target_label = load_data(data_path_t,label_path_t)
print(source_data.shape,source_label.shape)
print(target_data.shape,target_label.shape)nDataSet = 1#sample timesacc = np.zeros([nDataSet, 1])
A = np.zeros([nDataSet, CLASS_NUM])
k = np.zeros([nDataSet, 1])BATCH_SIZE = 64
acc_all_ndataset = []
clean_acc_all = []
val_all_ndataset = []
val_acc_ndataset = []
best_predict_all = 0
best_test_acc = 0
train_loss_ndataset = []
best_G,best_RandPerm,best_Row,best_Column = None,None,None,None
# 当前epoch,源域loader,目标域loader,20
def train(ep, data_loader, data_loader_t,train_epoch,weight_clean):criterion_s = nn.CrossEntropyLoss().cuda()criterion_t = nn.CrossEntropyLoss(weight=weight_clean).cuda()gamma = 0.01alpha = 0.1beta = 0.01for batch_idx, data in enumerate(zip(data_loader, data_loader_t)):G.train()F1.train()F2.train()if ep >= train_epoch: # epoch大于20时,目标域已经有伪标签了。这个伪标签是根据分类器直接预测的(data_s, label_s), (data_t, fake_label_t) = datafake_label_t = Variable(fake_label_t).cuda()else:(data_s, label_s), (data_t, _) = dataif args.cuda:data_s, label_s = data_s.cuda(), label_s.cuda()data_t = data_t.cuda()data_all = Variable(torch.cat((data_s, data_t), 0))label_s = Variable(label_s)bs = len(label_s)"""source domain discriminative"""# Step A train all networks to minimize loss on sourceoptimizer_g.zero_grad()optimizer_f.zero_grad()output = G(data_all)# 分类器训练 三个全连接层output1 = F1(output)output2 = F2(output)output_s1 = output1[:bs, :]  # 第一个分类器在源域的分类结果output_s2 = output2[:bs, :]  # 第二个分类器,源域output_t1 = output1[bs:, :]  # 第一个分类器,目标域output_t2 = output2[bs:, :]  # 第二个分类器,目标域output_t1_prob = F.softmax(output_t1)  # 目标域在两个分类器的预测output_t2_prob = F.softmax(output_t2)# 目标域分类结果在两个分类器上的熵entropy_loss = - torch.mean(torch.log(torch.mean(output_t1_prob, 0) + 1e-6))entropy_loss -= torch.mean(torch.log(torch.mean(output_t2_prob, 0) + 1e-6))# 源域在两个分类器的分类损失loss1 = criterion_s(output_s1, label_s)loss2 = criterion_s(output_s2, label_s)# 如果当前epoch大于20,计算目标域的分类损失?if ep >= train_epoch:target_loss = criterion_t(output_t1, fake_label_t) + criterion_t(output_t2, fake_label_t)entroy_target_loss = utils.EntropyLoss(output_t1_prob) + utils.EntropyLoss(output_t2_prob)else:target_loss = 0entroy_target_loss= 0all_loss = loss1 + loss2 + 0.01 * entropy_loss +  alpha *  target_loss +beta * entroy_target_lossall_loss.backward()optimizer_g.step()optimizer_f.step()"""target domain discriminative"""# Step B train classifier to maximize discrepancyoptimizer_g.zero_grad()optimizer_f.zero_grad()output = G(data_all)output1 = F1(output)output2 = F2(output)output_s1 = output1[:bs, :]output_s2 = output2[:bs, :]output_t1 = output1[bs:, :]output_t2 = output2[bs:, :]output_t1 = F.softmax(output_t1)output_t2 = F.softmax(output_t2)loss1 = criterion_s(output_s1, label_s)loss2 = criterion_s(output_s2, label_s)entropy_loss = - torch.mean(torch.log(torch.mean(output_t1, 0) + 1e-6))entropy_loss -= torch.mean(torch.log(torch.mean(output_t2, 0) + 1e-6))loss_dis = utils.cdd(output_t1, output_t2)F_loss = loss1 + loss2 - gamma * loss_dis + 0.01 * entropy_lossF_loss.backward()optimizer_f.step()# Step C train genrator to minimize discrepancyfor i in range(num_k):optimizer_g.zero_grad()optimizer_f.zero_grad()output = G(data_all)output1 = F1(output)output2 = F2(output)output_t1 = output1[bs:, :]output_t2 = output2[bs:, :]output_t1_prob = F.softmax(output_t1)output_t2_prob = F.softmax(output_t2)entropy_loss = - torch.mean(torch.log(torch.mean(output_t1_prob, 0) + 1e-6))entropy_loss -= torch.mean(torch.log(torch.mean(output_t2_prob, 0) + 1e-6))loss_dis = utils.cdd(output_t1_prob, output_t2_prob)D_loss = gamma * loss_dis + 0.01 * entropy_lossD_loss.backward()optimizer_g.step()print('Train Ep: {} \ttrian_target_dataset:{}\tLoss1: {:.6f}\tLoss2: {:.6f}\t Dis: {:.6f} Entropy: {:.6f} '.format(ep, len(data_loader_t.dataset),loss1.item(), loss2.item(), loss_dis.item(), entropy_loss.item()))def get_probs(data_loader,data_loader_t):train_features, train_labels = utils.extract_embeddings(G, data_loader)clt = svm.SVC(probability=True)clt.fit(train_features, train_labels)test_features, test_labels = utils.extract_embeddings(G, data_loader_t)probs = clt.predict_proba(test_features)return probsdef clean_sampling_epoch(labels, probabilities):labels = np.array(labels)probabilities = np.array(probabilities)#find the error samples indexlabel_error_mask = np.zeros(len(labels), dtype=bool)label_error_indices = cleanlab.count.compute_confident_joint(labels, probabilities, return_indices_of_off_diagonals=True)[1]for idx in label_error_indices:label_error_mask[idx] = True# label_errors_bool = cleanlab.pruning.get_noise_indices(labels, probabilities, prune_method='prune_by_class',n_jobs=1)label_errors_bool = cleanlab.filter.find_label_issues(labels, probabilities,# filter_by='prune_by_class',n_jobs=1)ordered_label_errors = cleanlab.rank.order_label_issues(label_issues_mask=label_errors_bool,labels=labels,pred_probs=probabilities,# rank_by='normalized_margin',# label_errors_bool=label_errors_bool,# psx=probabilities,# labels=labels,# sorted_index_method='normalized_margin',)# ordered_label_errors = cleanlab.pruning.order_label_errors(#     label_errors_bool=label_errors_bool,#     psx=probabilities,#     labels=labels,#     sorted_index_method='normalized_margin',# )true_labels_idx = []all_labels_idx = []for i in range(len(labels)):all_labels_idx.append(i)if len(ordered_label_errors) == 0:true_labels_idx = all_labels_idxelse:for j in range(len(ordered_label_errors)):all_labels_idx.remove(ordered_label_errors[j])true_labels_idx = all_labels_idxorig_class_count = np.bincount(labels,minlength = CLASS_NUM)train_bool_mask = ~label_errors_boolimgs = [labels[i] for i in range(len(labels)) if train_bool_mask[i] ]clean_class_counts = np.bincount(imgs,minlength = CLASS_NUM)# compute the class weights to re-weight loss during trainingclass_weights = torch.Tensor(orig_class_count / clean_class_counts).cuda()target_datas = []target_labels = []for i in range(len(true_labels_idx)):target_datas.append(testX[true_labels_idx[i]])target_labels.append(labels[true_labels_idx[i]])target_datas = np.array(target_datas)target_labels = np.array(target_labels)return target_datas, target_labels, class_weightsdef test(data_loader):test_pred_all = []test_all = []predict = np.array([], dtype=np.int64)G.eval()F1.eval()F2.eval()test_loss = 0correct_add = 0size = 0for batch_idx, data in enumerate(data_loader):img, label = dataimg, label = img.cuda(), label.cuda()img, label = Variable(img, volatile=True), Variable(label)output = G(img)output1 = F1(output)output2 = F2(output)output_add = output1 + output2  # 对应位置特征相加pred = output_add.data.max(1)[1]test_loss += F.nll_loss(F.log_softmax(output1, dim=1), label, size_average=False).item()correct_add += pred.eq(label.data).cpu().sum()  # correctsize += label.data.size()[0]  # totaltest_all = np.concatenate([test_all, label.data.cpu().numpy()])test_pred_all = np.concatenate([test_pred_all, pred.cpu().numpy()])predict = np.append(predict, pred.cpu().numpy())test_accuracy = 100. * float(correct_add) / sizetest_loss /= len(data_loader.dataset)  # loss function already averages over batch sizeprint('Epoch: {:d} Test set:test loss:{:.6f}, Accuracy: {}/{} ({:.6f}%)'.format(ep, test_loss, correct_add, size, 100. * float(correct_add) / size))acc[iDataSet] = 100. * float(correct_add) / sizeOA = accC = metrics.confusion_matrix(test_all, test_pred_all)A[iDataSet, :] = np.diag(C) / np.sum(C, 1, dtype=np.float)k[iDataSet] = metrics.cohen_kappa_score(test_all, test_pred_all)return test_accuracy, predictfor iDataSet in range(nDataSet):print('#######################idataset######################## ', iDataSet)np.random.seed(seeds[iDataSet])# data# 返回了源域的训练样本和标签[1260,102,5,5],[1260,]。# train_test_preclass的作用是随机为每个label取了固定值的像素,并且取到了这个像素周围的值,得到一个块作为样本train_xs, train_ys = train_test_preclass(source_data, source_label, HalfWidth, 180)# 目标域同理,这里all_data的函数是因为对于目标域不需要分训练集和测试集,所以目标域是全部数据[39355,102,5,5]testX, testY, G_test, RandPerm, Row, Column = all_data(target_data, target_label, HalfWidth)  # (7826,5,5,72)train_dataset = TensorDataset(torch.tensor(train_xs), torch.tensor(train_ys))train_t_dataset = TensorDataset(torch.tensor(testX), torch.tensor(testY))train_loader_s = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True, drop_last=True)train_loader_t = DataLoader(train_t_dataset, batch_size=BATCH_SIZE, shuffle=True, drop_last=True)test_loader = DataLoader(train_t_dataset, batch_size=BATCH_SIZE, shuffle=False)# model 102,128,5,7G = basenet.EmbeddingNetHyperX(nBand, n_outputs=n_outputs, patch_size=patch_size, n_classes=CLASS_NUM).cuda()F1 = basenet.ResClassifier(num_classes=CLASS_NUM, num_unit=G.output_num(), middle=64)F2 = basenet.ResClassifier(num_classes=CLASS_NUM, num_unit=G.output_num(), middle=64)lr = args.lrif args.cuda:G.cuda()F1.cuda()F2.cuda()# optimizer and lossoptimizer_g = optim.SGD(list(G.parameters()), lr=args.lr, weight_decay=0.0005)optimizer_f = optim.SGD(list(F1.parameters()) + list(F2.parameters()), momentum=args.momentum, lr=args.lr,weight_decay=0.0005)train_num = 20class_weights = Nonefor ep in range(1,num_epoch+1):if (ep >= train_num and ep < num_epoch) and ep % 20 == 0 :print('get  fake label,ep = ',ep)fake_label = utils.obtain_label(test_loader, G, F1, F2)label_list = list(set(fake_label))print(label_list)if len(label_list) != CLASS_NUM:breakprint('get probs,ep=',ep)probs = get_probs(train_loader_s, test_loader)clean_datas, clean_labels, class_weights = clean_sampling_epoch(fake_label, probs)target_datasets = TensorDataset(torch.tensor(clean_datas), torch.tensor(clean_labels))train_loader_t = DataLoader(target_datasets, batch_size=BATCH_SIZE, shuffle=True, num_workers=0,drop_last=True)train(ep, train_loader_s, train_loader_t, train_num, class_weights)print('-' * 100, '\nTesting')test_accuracy, predict = test(test_loader)if test_accuracy >= best_test_acc:best_test_acc = test_accuracybest_predict_all = predictbest_G, best_RandPerm, best_Row, best_Column = G_test, RandPerm, Row, Columnbest_iDataSet = iDataSettorch.save({'netG':G.state_dict(),'F1':F1.state_dict(),'F2':F2.state_dict()},'checkpoints/pavia/model_test'+str(iDataSet)+'.pt')print(acc)
AA = np.mean(A, 1)  # size[1],如果iDataset=1,那么这时AA=AAmean
AAMean = np.mean(AA, 0) #
AAStd = np.std(AA)
AMean = np.mean(A, 0)
AStd = np.std(A, 0)
OAMean = np.mean(acc)
OAStd = np.std(acc)
kMean = np.mean(k)
kStd = np.std(k)print("average OA: " + "{:.2f}".format(OAMean) + " +- " + "{:.2f}".format(OAStd))
print("average AA: " + "{:.2f}".format(100 * AAMean) + " +- " + "{:.2f}".format(100 * AAStd))
print("average kappa: " + "{:.4f}".format(100 * kMean) + " +- " + "{:.4f}".format(100 * kStd))
print("accuracy for each class: ")
for i in range(CLASS_NUM):print("Class " + str(i) + ": " + "{:.2f}".format(100 * AMean[i]) + " +- " + "{:.2f}".format(100 * AStd[i]))print('classification map!!!!!')
for i in range(len(best_predict_all)):best_G[best_Row[best_RandPerm[ i]]][best_Column[best_RandPerm[ i]]] = best_predict_all[i] + 1import matplotlib.pyplot as plt
# [1096,715,3]  best_G:[1096,715],dpi=24
def classification_map(map, groundTruth, dpi, savePath):fig = plt.figure(frameon=False)# 715*2/24, 1096*2/24fig.set_size_inches(groundTruth.shape[1]*2.0/dpi, groundTruth.shape[0]*2.0/dpi)ax = plt.Axes(fig, [0., 0., 1., 1.])ax.set_axis_off()ax.xaxis.set_visible(False)ax.yaxis.set_visible(False)fig.add_axes(ax)ax.imshow(map)fig.savefig(savePath, dpi = dpi)return 0###################################################
# [1100,719,3]  best_G:[1100,719]
hsi_pic = np.zeros((best_G.shape[0], best_G.shape[1], 3))
for i in range(best_G.shape[0]):for j in range(best_G.shape[1]):if best_G[i][j] == 0:hsi_pic[i, j, :] = [0, 0, 0]if best_G[i][j] == 1:hsi_pic[i, j, :] = [0, 0, 1]if best_G[i][j] == 2:hsi_pic[i, j, :] = [0, 1, 0]if best_G[i][j] == 3:hsi_pic[i, j, :] = [0, 1, 1]if best_G[i][j] == 4:hsi_pic[i, j, :] = [1, 0, 0]if best_G[i][j] == 5:hsi_pic[i, j, :] = [1, 0, 1]if best_G[i][j] == 6:hsi_pic[i, j, :] = [1, 1, 0]if best_G[i][j] == 7:hsi_pic[i, j, :] = [0.5, 0.5, 1]classification_map(hsi_pic[2:-2, 2:-2, :], best_G[2:-2, 2:-2], 24, "./classificationMap/PC.png")
#

数据预处理

def all_data(Data_Band_Scaler, GroundTruth,HalfWidth):print(Data_Band_Scaler.shape)[nRow, nColumn, nBand] = Data_Band_Scaler.shape  # [1096,715,102]'''label start'''# 一样的,先是变成特别大的外面全是0的矩阵data_band_scaler = flip(Data_Band_Scaler)  # [3288,2145,102]groundtruth = flip(GroundTruth)  #HalfWidth = HalfWidth# 变成只有外边两层0的数据和标签G = groundtruth[nRow - HalfWidth:2 * nRow + HalfWidth, nColumn - HalfWidth:2 * nColumn + HalfWidth]  # (642, 372)data = data_band_scaler[nRow - HalfWidth:2 * nRow + HalfWidth, nColumn - HalfWidth:2 * nColumn + HalfWidth, :]  # (642, 372, 103)# 取非0位置的索引,他俩一起能确定一个像素值[Row, Column] = np.nonzero(G)train = {}m = int(np.max(G))  # 最大值为7,也就是说,标签是1-7# 对每个类别取样,得到每个类别的行索引for i in range(m):# 这里索引的时候用到了行和列,所以后面只需要用行的索引就可以了indices = [j for j, x in enumerate(Row.ravel().tolist()) if G[Row[j], Column[j]] == i + 1]  # G ndarray Row中的索引np.random.shuffle(indices)  #train[i] = indicestrain_indices = []for i in range(m):train_indices += train[i]np.random.shuffle(train_indices)print('the number of target:', len(train_indices))  # 520nTrain = len(train_indices)  # 520trainX = np.zeros([nTrain,  nBand, 2 * HalfWidth + 1, 2 * HalfWidth + 1], dtype=np.float32)trainY = np.zeros([nTrain], dtype=np.int64)RandPerm = train_indicesRandPerm = np.array(RandPerm)for i in range(nTrain):trainX[i, :, :, :] = np.transpose(data[Row[RandPerm[i]] - HalfWidth: Row[RandPerm[i]] + HalfWidth + 1, \Column[RandPerm[i]] - HalfWidth: Column[RandPerm[i]] + HalfWidth + 1, :], (2,0,1))trainY[i] = G[Row[RandPerm[i]], Column[RandPerm[i]]].astype(np.int64)trainY = trainY - 1print('all data shape',trainX.shape)print('all label shape',trainY.shape)return trainX,trainY,G,RandPerm,Row, Column

可理解为切片

def train_test_preclass(Data_Band_Scaler, GroundTruth,HalfWidth,labeled_number):print(Data_Band_Scaler.shape)[nRow, nColumn, nBand] = Data_Band_Scaler.shape # 分别是图像的宽高、通道数data_band_scaler = flip(Data_Band_Scaler)  # (1830, 1020, 103)groundtruth = flip(GroundTruth)  # (1830, 1020)HalfWidth = HalfWidth# G 相当于是对原始GT[610,340]外圈加了宽度为HalfWidth的0,[614,344]G = groundtruth[nRow - HalfWidth:2 * nRow + HalfWidth, nColumn - HalfWidth:2 * nColumn + HalfWidth]  # (642, 372)# data相当立方体四周加0 [614,344,102]data = data_band_scaler[nRow - HalfWidth:2 * nRow + HalfWidth, nColumn - HalfWidth:2 * nColumn + HalfWidth, :]  # (642, 372, 103)# np.nonzero函数是numpy中用于得到数组array中非零元素的位置(数组索引)的函数# 从行和列上两个维度上各用一个数组来描述非零索引值[Row, Column] = np.nonzero(G)  # (39332,) (39332,) 根据G确定样本所在的行和列# 这三个dict用于保存各个类别id对应的像素点索引labels_loc = {}train = {}test = {}m = int(np.max(G))  # 7#标样本的个数nlabeled = labeled_number # 每个类别取180个样本#取样 对每个类别取样for i in range(m):# ravel()方法将数组维度拉成一维数组,这里的indices取到了类别为i+1的像素的行索引indices = [j for j, x in enumerate(Row.ravel().tolist()) if G[Row[j], Column[j]] == i + 1]  # G ndarray Row中的索引np.random.shuffle(indices)  # 对取到的像素点打乱nb_val = nlabeled  # 180labels_loc[i] = indicestrain[i] = indices[:nb_val]  # 取前180个用于训练,后面剩余的用于测试test[i] = indices[nb_val:]# 这两个列表按顺序存储了用于训练和测试的各个类别对应的位置索引train_indices = []test_indices = []for i in range(m):train_indices += train[i]test_indices += test[i]# 索引打乱np.random.shuffle(train_indices) # let the same class has different indexnp.random.shuffle(test_indices)print('the number of the train samples:', len(train_indices))  # 180*7=1260print('the number of the test samples:', len(test_indices))  # 剩余38072nTrain = len(train_indices) # 长度为1260的索引nTest = len(test_indices)  # 38072# [1260,102,5,5] 一共1260个像素点,每个像素点的通道数是102trainX = np.zeros([nTrain,  nBand, 2 * HalfWidth + 1, 2 * HalfWidth + 1], dtype=np.float32)# (1260,)trainY = np.zeros([nTrain], dtype=np.int64)# [38072.102,5,5]testX = np.zeros([nTest,  nBand, 2 * HalfWidth + 1, 2 * HalfWidth + 1], dtype=np.float32)testY = np.zeros([nTest], dtype=np.int64)RandPerm = train_indices + test_indicesRandPerm = np.array(RandPerm)# 对每个训练像素点for i in range(nTrain):# 为一个【102,5,5】的块赋值,这个值是这个像素周围的区域,相当于把每个像素都变成了一块值,而不是一个值trainX[i, :, :, :] = np.transpose(data[Row[RandPerm[i]] - HalfWidth: Row[RandPerm[i]] + HalfWidth + 1, \Column[RandPerm[i]] - HalfWidth: Column[RandPerm[i]] + HalfWidth + 1, :], (2,0,1))trainY[i] = G[Row[RandPerm[i]], Column[RandPerm[i]]].astype(np.int64)trainY = trainY - 1for i in range(nTest):testX[i, :, :, :] = np.transpose(data[Row[RandPerm[i+nTrain]] - HalfWidth: Row[RandPerm[i+nTrain]] + HalfWidth + 1, \Column[RandPerm[i+nTrain]] - HalfWidth: Column[RandPerm[i+nTrain]] + HalfWidth + 1, :], (2,0,1))testY[i] = G[Row[RandPerm[i+nTrain]], Column[RandPerm[i+nTrain]]].astype(np.int64)testY = testY - 1print('train data shape',trainX.shape)print('train label shape',trainY.shape)print('test data shape',testX.shape)print('test label shape',testY.shape)return trainX,trainY

高光谱(二)Confident Learning-Based Domain Adaptation for Hyperspectral Image Classification相关推荐

  1. Contrastive Learning Based on Transformer for Hyperspectral Image Classification

    自娱自乐对比学习高光谱图像分类第二篇 1. Introduction 在高光谱图像分类中 3D 比 2D 好?不知道这句话怎么得来的. 无监督学习: 表示学习(AE, GAN) 判别学习 – cont ...

  2. 遥感图像-Deep Feature Alignment Neural Networks for Domain Adaptation of Hyperspectral Data高光谱数据深度特征对齐神经

    Deep Feature Alignment Neural Networks for Domain Adaptation of Hyperspectral Data高光谱数据领域自适应的深度特征对齐神 ...

  3. ICCV2019-SSF-DAN: Separated Semantic Feature based Domain Adaptation Network for Semantic Segmentati

    SSF-DAN: Separated Semantic Feature based Domain Adaptation Network for Semantic Segmentation 基于分离语义 ...

  4. 论文笔记-SSF-DAN: Separated Semantic Feature based Domain Adaptation Network for Semantic Segmentation

    论文信息 论文标题:SSF-DAN: Separated Semantic Feature based Domain Adaptation Network for Semantic Segmentat ...

  5. 【域自适应】Dual Path Learning for Domain Adaptation of Semantic Segmentation

    文章目录 摘要 1.介绍 2.相关工作 3.方法 3.1. Single Path Warm-up 3.2. Dual Path Image Translation 3.3. Dual Path Ad ...

  6. 【ICML 2015迁移学习论文阅读】Unsupervised Domain Adaptation by Backpropagation (DANN) 无监督领域自适应

    会议:ICML 2015 论文题目:Unsupervised Domain Adaptation by Backpropagation 论文地址:http://proceedings.mlr.pres ...

  7. 2020 Domain Adaptation 最新论文:插图速览(三)

    2020 Domain Adaptation 最新论文:插图速览(三) 目录 Learning to Combine: Knowledge Aggregation for Multi-Source D ...

  8. 语义分割-Unsupervised Domain Adaptation in Semantic Segmentation:a Review语义分割中的无监督领域自适应:综述

    Unsupervised Domain Adaptation in Semantic Segmentation:a Review语义分割中的无监督领域自适应:综述 0.摘要 1.介绍 1.1.语义分割 ...

  9. Domain adaptation from daytime to nighttime: A situation-sensitive vehicle detection and traffic…(翻)

    Title:Domain adaptation from daytime to nighttime: A situation-sensitive vehicle detection and traff ...

  10. 主动领域自适应(Active Domain Adaptation)部分经典论文汇总

    只简单找了一小部分 CVPR [link] [code] [TQS] [21] Transferable Query Selection for Active Domain Adaptation [l ...

最新文章

  1. 从官网下载的python包如何使用-如何下载python包
  2. junit 测试执行顺序_JUnit 5中的测试执行顺序
  3. 网站设计软件linux,ubuntu下的网页设计 网页制作软件工具.pdf
  4. element el-tree懒加载+搜索
  5. 仿星球大战个人引导页源码
  6. 一列对应右侧几行html,css查找表格第几行第几列
  7. 抖音网红mac桌宠Desktop Goose呆头鹅的使用教程
  8. 有什么相见恨晚的算法答题套路?【力扣】
  9. 绕过tp路由器管理密码_TP-LINK 无线路由器设置详解
  10. 使用GitHub小总结
  11. 书摘—20几岁不学应酬,30几岁只能发愁
  12. 开机黑屏显示html,电脑开机显示display going to sleep怎么办?
  13. win7 访问局域网共享文件时提示输入网络凭据 设置开机免输入凭证进入共享盘设置
  14. 量化交易软件该怎么选择
  15. C语言之const和volatile究极学习
  16. c语言编程题蓄水池,C语言中蓄水池抽样
  17. 选择 Delphi 2007 ( CodeGear Delphi 2007 for Win32 Version 11.0.2837.9583 ) 的理由
  18. uniapp报错 -4048
  19. 命令行mysql数据库备份_MySQL命令行备份数据库
  20. matlab stem 属性,matlab中stem函数用法_常见问题解析

热门文章

  1. 第五课 Shell脚本编程-awk用法
  2. vim编辑器的复制、粘贴、删除
  3. 美国顶级商学院将增设加密货币课程
  4. 洛谷 P2051 [AHOI2009]中国象棋【dp】
  5. 按钮 java_java如何创建并设置一个按钮
  6. springboot: mybatis的使用
  7. 25个精美的Jquery Mobile手机网站模板
  8. 每隔一段时间更换一次微信
  9. Unity Shader 之 Geometry Shader 简单实现物体线框呈现的效果
  10. ios学习笔记 (4)数据持久化