单序列和多序列模型的训练train

单序列模型的训练

import os

os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
import os
import sys
import argparse
import time
from datetime import datetime
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.nn import CosineEmbeddingLoss
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

# 需要修改“resnet50” 
from models.resnet50 import resnet50 as model
from conf import settings
from utils import get_network, WarmUpLR, \
    most_recent_folder, most_recent_weights, last_epoch, best_acc_weights
from dataset import CESM

# 指定保存数据的文件夹路径
folder_path = r'C:\Users\Raytrack\Desktop\CT'

my_train_loss = []
my_eval_loss = []
my_train_correct = []
my_eval_correct = []


def train(epoch):
    start = time.time()
    train_loss = 0.0  # cost function error
    correct = 0.0
    net.train()
    net3.train()
    p = 0
    for i, x in enumerate(CESM_10_train_l):
        low_energy = x['LOW_ENERGY']
        # high_energy = x['HIGH_ENERGY']
        # enhance = x['ENHANCE']

        labels = x['label']
        labels = torch.LongTensor(labels.numpy())
        # labels = torch.IntTensor(labels).to(torch.long)

        if args.gpu:
            low_energy = low_energy.to(device)
            # high_energy = high_energy.to(device)
            # enhance = enhance.to(device)
            labels = labels.to(device)

        optimizer.zero_grad()
        outputs_low_energy, ou_CCL = net(low_energy)
        # outputs_high_energy,ou_CCR = net(high_energy)
        # outputs_enhance,ou_MLOL = net(enhance)

        # outputs1 = torch.cat((outputs_low_energy  #, outputs_high_energy,outputs_enhance
        #                     ), dim=1)

        ou11 = net3(outputs_low_energy)
        loss = loss_function(ou11, labels)
        print('loss:{}'.format(
            loss.item()
        )

        )

        loss.backward()
        optimizer.step()
        train_loss += loss.sum().item()
        _, preds = ou11.max(1)

        correct += preds.eq(labels).sum()
        n_iter = (epoch - 1) * len(CESM_10_train_l) + i + 1

        print('Training Epoch: {epoch} [{trained_samples}/{total_samples}]\t Train Loss: {:0.4f}\tLR: {:0.6f}'.format(
            loss.item(),
            optimizer.param_groups[0]['lr'],
            # correct.float() / len(CESMdata),
            epoch=epoch,
            trained_samples=i * args.b + len(low_energy),
            total_samples=len(CESMdata)
        ))

        if epoch <= args.warm:
            warmup_scheduler.step()

    train_loss_ = train_loss / (len(CESMdata))
    train_correct = correct / (len(CESMdata))
    my_train_loss.append(train_loss_)
    my_train_correct.append(train_correct.cpu())

    finish = time.time()

    print('epoch {} training time consumed: {:.2f}s'.format(epoch, finish - start))
    print('Train Average loss: {:.4f}\tTrain Accuarcy: {:0.6f}'.format(
        train_loss / len(CESMdata),
        correct.cpu() / (len(CESMdata))
    ))


@torch.no_grad()
def eval_training(epoch=0, tb=True):
    start = time.time()
    net.eval()
    net3.eval()
    test_loss = 0.0  # cost function error
    correct = 0.0
    correct2 = 0.0

    for i, x in enumerate(CESM_10_test_l):

        low_energy = x['LOW_ENERGY']
        # high_energy = x['HIGH_ENERGY']
        # enhance = x['ENHANCE']

        labels = x['label']
        labels = torch.LongTensor(labels.numpy())
        # labels = torch.IntTensor(labels).to(torch.long)

        if args.gpu:
            low_energy = low_energy.to(device)
            # high_energy = high_energy.to(device)
            # enhance = enhance.to(device)
            labels = labels.to(device)

        optimizer.zero_grad()
        outputs_low_energy, ou_CCL = net(low_energy)
        # outputs_high_energy,ou_CCR = net(high_energy)
        # outputs_enhance,ou_MLOL = net(enhance)

        # outputs1 = torch.cat((outputs_low_energy#, outputs_high_energy,outputs_enhance
        #                      ), dim=1)

        ou11 = net3(outputs_low_energy)
        loss = loss_function(ou11, labels)

        n_iter = (epoch - 1) * len(CESM_10_test_l) + i + 1
        test_loss += loss.sum().item()
        _, preds = ou11.max(1)
        correct += preds.eq(labels).sum()

    test_loss_ = test_loss / (len(CESMdata2))
    my_eval_loss.append(test_loss_)
    eval_correct = correct / (len(CESMdata2))
    my_eval_correct.append(eval_correct.cpu())

    finish = time.time()

    if args.gpu:
        print('GPU INFO.....')
        print(torch.cuda.memory_summary(), end='')
    print('Evaluating Network.....')
    print('Eval set: Epoch: {},Eval Average loss: {:.4f},Eval Accuracy: {:.4f} Time consumed:{:.2f}s'.format(
        epoch,
        test_loss / len(CESMdata2),
        correct.cpu() / (len(CESMdata2)),
        finish - start
    ))
    print()

    # 需要修改保存每一轮的损失和正确率到loss1中
    np.savez(os.path.join(folder_path, 'loss1.npz'), my_train_loss=my_train_loss, my_eval_loss=my_eval_loss,
             my_train_correct=my_train_correct, my_eval_correct=my_eval_correct)

    return correct.cpu() / (len(CESMdata2))


if __name__ == '__main__':
    # 共需要修改四处,加上导入模型为五处
    parser = argparse.ArgumentParser()
    # parser.add_argument('-net', type=str, required=True, help='net type')
    parser.add_argument('-device', action='store_true', default='cuda', help='device id (i.e.0or 0,1 or cpu)')
    parser.add_argument('-b', type=int, default=50, help='batch size for dataloader')
    parser.add_argument('-warm', type=int, default=0, help='warm up training phase')
    parser.add_argument('-lr', type=float, default=0.001, help='initial learning rate')
    parser.add_argument('-resume', action='store_true', default=False, help='resume training')
    args = parser.parse_args()
    
    # 检查是否有可用的 CUDA 设备,如果没有,则使用 CPU
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    if device.type == "cuda":
        print("Device GPUid:{} is available".format(torch.cuda.current_device()))
    else:
        print("CUDA is not available, using CPU for training.")

    # 需要修改“resnet50” 
    net = model()

    net = net.to(device)

    # path1 = 'pretrained models'
    # net.load_state_dict(torch.load(path1),strict=False)
    net3 = nn.Linear(512, 2)
    net3.to(device)

    CESMdata = CESM(base_dir=r'C:\Users\Raytrack\Documents\CR的最后数据集代码\MF\h5py\train',
                    transform=transforms.Compose([
                        # Random表示有可能做,所以也可能不做
                        transforms.RandomHorizontalFlip(p=0.5),  # 水平翻转
                        transforms.RandomVerticalFlip(p=0.5),  # 上下翻转
                        transforms.RandomRotation(10),  # 随机旋转-10°~10°
                        # transforms.RandomRotation([90, 180]), # 随机在90°、180°中选一个度数来旋转,如果想有一定概率不旋转,可以加一个0进去
                        # transforms.ColorJitter(brightness=0.3, contrast=0.3, hue=0.3)
                        # transforms.Normalize(0, 1)
                        transforms.ToTensor(),

                    ]))
    CESM_10_train_l = DataLoader(CESMdata, batch_size=args.b, shuffle=True, drop_last=False,
                                 pin_memory=torch.cuda.is_available())

    CESMdata2 = CESM(base_dir=r'C:\Users\Raytrack\Documents\CR的最后数据集代码\MF\h5py\valid',
                     transform=transforms.Compose([
                         transforms.ToTensor(),
                     ]))
    CESM_10_test_l = DataLoader(CESMdata2, batch_size=args.b, shuffle=False, drop_last=False,
                                pin_memory=torch.cuda.is_available())

    loss_function = nn.CrossEntropyLoss()
    loss_function.to(device)

    optimizer = optim.SGD([{"params": net.parameters()}, {"params": net3.parameters()}], lr=args.lr, momentum=0.9,
                          weight_decay=5e-4)
    train_scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=settings.MILESTONES,
                                                     gamma=0.5)  # learning rate decay
    iter_per_epoch = len(CESM_10_train_l)
    warmup_scheduler = WarmUpLR(optimizer, iter_per_epoch * args.warm)

    if args.resume:
        recent_folder = most_recent_folder(os.path.join(settings.CHECKPOINT_PATH, args.net), fmt=settings.DATE_FORMAT)
        if not recent_folder:
            raise Exception('no recent folder were found')
        # 需要修改“resnet50”        
        checkpoint_path = os.path.join(settings.CHECKPOINT_PATH, 'resnet50', recent_folder)
    # 需要修改“resnet50” 
    else:
        checkpoint_path = os.path.join(settings.CHECKPOINT_PATH, 'resnet50', settings.TIME_NOW)

    # create checkpoint folder to save model
    if not os.path.exists(checkpoint_path):
        os.makedirs(checkpoint_path)
    checkpoint_path = os.path.join(checkpoint_path, '{net}-{epoch}-{type}.pth')

    best_acc = 0.0
    best_acc2 = 0.0
    if args.resume:
        best_weights = best_acc_weights(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))
        if best_weights:
            weights_path = os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder, best_weights)
            print('found best acc weights file:{}'.format(weights_path))
            print('load best training file to test acc...')
            net.load_state_dict(torch.load(weights_path))
            best_acc = eval_training(tb=False)
            print('best acc is {:0.2f}'.format(best_acc))

        recent_weights_file = most_recent_weights(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))
        if not recent_weights_file:
            raise Exception('no recent weights file were found')
        weights_path = os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder, recent_weights_file)
        print('loading weights file {} to resume training.....'.format(weights_path))
        net.load_state_dict(torch.load(weights_path))

        resume_epoch = last_epoch(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))

    for epoch in range(1, settings.EPOCH + 1):
        if epoch > args.warm:
            train_scheduler.step(epoch)

        if args.resume:
            if epoch <= resume_epoch:
                continue

        train(epoch)
        acc = eval_training(epoch)
        # 需要修改“resnet50” 
        # start to save best performance model after learning rate decay to 0.01
        if epoch <= settings.MILESTONES[3] and best_acc < acc:
            weights_path = checkpoint_path.format(net='resnet50', epoch=epoch, type='best')
            weights_path3 = checkpoint_path.format(net='net3', epoch=epoch, type='best')
            print('saving weights file to {}'.format(weights_path))
            torch.save(net.state_dict(), weights_path)
            torch.save(net3.state_dict(), weights_path3)
            best_acc = acc

            continue

    # 保存 label 和 pro 到一个文件
    np.savez(os.path.join(folder_path, 'loss.npz'), my_train_loss=my_train_loss, my_eval_loss=my_eval_loss,
             my_train_correct=my_train_correct, my_eval_correct=my_eval_correct)
    print('my_train_loss:', len(my_train_loss))
    print('my_eval_loss:', len(my_eval_loss))
    print('my_train_correct:', my_train_correct)
    print('my_eval_correct:', my_eval_correct)

多序列模型的训练

import os
import sys
import argparse
import time
from datetime import datetime

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.nn import CosineEmbeddingLoss

from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

# 需要改为Vgg
from models.vgg import *
from conf import settings
from utils import get_network, WarmUpLR, \
    most_recent_folder, most_recent_weights, last_epoch, best_acc_weights
from dataset import CESM

# 指定保存数据的文件夹路径
folder_path = r'C:\Users\Raytrack\Desktop\MR'

my_train_loss = []
my_eval_loss = []
my_train_correct = []
my_eval_correct = []


def train(epoch):
    start = time.time()
    train_loss = 0.0  # cost function error
    correct = 0.0
    net.train()
    net3.train()
    p = 0
    for i, x in enumerate(CESM_10_train_l):
        low_energy = x['LOW_ENERGY']
        high_energy = x['HIGH_ENERGY']
        enhance = x['ENHANCE']

        labels = x['label']
        labels = torch.LongTensor(labels.numpy())
        # labels = torch.IntTensor(labels).to(torch.long)

        if args.gpu:
            low_energy = low_energy.to(device)
            high_energy = high_energy.to(device)
            enhance = enhance.to(device)
            labels = labels.to(device)

        optimizer.zero_grad()
        outputs_low_energy, ou_CCL = net(low_energy)
        outputs_high_energy, ou_CCR = net(high_energy)
        outputs_enhance, ou_MLOL = net(enhance)

        outputs1 = torch.cat((outputs_low_energy, outputs_high_energy, outputs_enhance), dim=1)

        ou11 = net3(outputs1)
        loss = loss_function(ou11, labels)
        print('loss:{}'.format(
            loss.item()
        )

        )

        loss.backward()
        optimizer.step()
        train_loss += loss.item()
        _, preds = ou11.max(1)

        correct += preds.eq(labels).sum()
        n_iter = (epoch - 1) * len(CESM_10_train_l) + i + 1

        print('Training Epoch: {epoch} [{trained_samples}/{total_samples}]\tLoss: {:0.4f}\tLR: {:0.6f}'.format(
            loss.item(),
            optimizer.param_groups[0]['lr'],
            # correct.float() / len(CESMdata),
            epoch=epoch,
            trained_samples=i * args.b + len(low_energy),
            total_samples=len(CESMdata)
        ))

        if epoch <= args.warm:
            warmup_scheduler.step()

    train_loss_ = train_loss / (len(CESMdata))
    train_correct = correct / (len(CESMdata))
    my_train_loss.append(train_loss_)
    my_train_correct.append(train_correct.cpu())

    finish = time.time()

    print('epoch {} training time consumed: {:.2f}s'.format(epoch, finish - start))
    print('Train Average loss: {:.4f}\tTrain Accuarcy: {:0.6f}'.format(
        train_loss / len(CESMdata),
        correct.cpu() / (len(CESMdata))
    ))


@torch.no_grad()
def eval_training(epoch=0, tb=True):
    start = time.time()
    net.eval()
    net3.eval()
    test_loss = 0.0  # cost function error
    correct = 0.0
    correct2 = 0.0

    for i, x in enumerate(CESM_10_test_l):

        low_energy = x['LOW_ENERGY']
        high_energy = x['HIGH_ENERGY']
        enhance = x['ENHANCE']

        labels = x['label']
        labels = torch.LongTensor(labels.numpy())
        # labels = torch.IntTensor(labels).to(torch.long)

        if args.gpu:
            low_energy = low_energy.to(device)
            high_energy = high_energy.to(device)
            enhance = enhance.to(device)
            labels = labels.to(device)

        optimizer.zero_grad()
        outputs_low_energy, ou_CCL = net(low_energy)
        outputs_high_energy, ou_CCR = net(high_energy)
        outputs_enhance, ou_MLOL = net(enhance)

        outputs1 = torch.cat((outputs_low_energy, outputs_high_energy, outputs_enhance), dim=1)

        ou11 = net3(outputs1)
        loss = loss_function(ou11, labels)

        n_iter = (epoch - 1) * len(CESM_10_test_l) + i + 1
        test_loss += loss.item()
        _, preds = ou11.max(1)
        correct += preds.eq(labels).sum()

    test_loss_ = test_loss / (len(CESMdata2))
    my_eval_loss.append(test_loss_)
    eval_correct = correct / (len(CESMdata2))
    my_eval_correct.append(eval_correct.cpu())

    finish = time.time()

    if args.gpu:
        print('GPU INFO.....')
        print(torch.cuda.memory_summary(), end='')
    print('Evaluating Network.....')
    print('Eval set: Epoch: {},Eval Average loss: {:.4f},Eval Accuracy: {:.4f} Time consumed:{:.2f}s'.format(
        epoch,
        test_loss / len(CESMdata2),
        correct.cpu() / (len(CESMdata2)),
        finish - start
    ))
    print()

    return correct.cpu() / (len(CESMdata2))


if __name__ == '__main__':
    # 一共要改4处“vgg16”,再加一次导入模型共修改5个地方
    parser = argparse.ArgumentParser()
    # parser.add_argument('-net', type=str,default='ResNet50', required=True, help='net type')
    parser.add_argument('-gpu', action='store_true', default=True, help='use gpu or not')
    parser.add_argument('-b', type=int, default=10, help='batch size for dataloader')
    parser.add_argument('-warm', type=int, default=0, help='warm up training phase')
    parser.add_argument('-lr', type=float, default=0.001, help='initial learning rate')
    parser.add_argument('-resume', action='store_true', default=False, help='resume training')
    args = parser.parse_args()
    
    # 检查是否有可用的 CUDA 设备,如果没有,则使用 CPU
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    if device.type == "cuda":
        print("Device GPUid:{} is available".format(torch.cuda.current_device()))
    else:
        print("CUDA is not available, using CPU for training.")
    
    # 这里需要哦改为“vgg16”
    net = vgg16_bn()
    net = net.to(device)

    # path1 = 'pretrained models'
    # net.load_state_dict(torch.load(path1),strict=False)
    net3 = nn.Linear(512 * 3, 2)
    net3.to(device)

    CESMdata = CESM(base_dir=r'C:\Users\Raytrack\Documents\325例乳腺癌数据代码\MF\h5py\train',
                    transform=transforms.Compose([
                        # Random表示有可能做,所以也可能不做
                        transforms.RandomHorizontalFlip(p=0.5),  # 水平翻转
                        transforms.RandomVerticalFlip(p=0.5),  # 上下翻转
                        transforms.RandomRotation(10),  # 随机旋转-10°~10°
                        # transforms.RandomRotation([90, 180]), # 随机在90°、180°中选一个度数来旋转,如果想有一定概率不旋转,可以加一个0进去
                        # transforms.ColorJitter(brightness=0.3, contrast=0.3, hue=0.3)
                        # transforms.Normalize(0, 1)
                        transforms.ToTensor(),

                    ]))
    CESM_10_train_l = DataLoader(CESMdata, batch_size=args.b, shuffle=True, drop_last=False,
                                 pin_memory=torch.cuda.is_available())

    CESMdata2 = CESM(base_dir=r'C:\Users\Raytrack\Documents\325例乳腺癌数据代码\MF\h5py\valid',
                     transform=transforms.Compose([
                         transforms.ToTensor(),
                     ]))
    CESM_10_test_l = DataLoader(CESMdata2, batch_size=args.b, shuffle=False, drop_last=False,
                                pin_memory=torch.cuda.is_available())

    loss_function = nn.CrossEntropyLoss()
    loss_function.to(device)

    optimizer = optim.SGD([{"params": net.parameters()}, {"params": net3.parameters()}], lr=args.lr, momentum=0.9,
                          weight_decay=5e-4)
    train_scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=settings.MILESTONES,
                                                     gamma=0.5)  # learning rate decay
    iter_per_epoch = len(CESM_10_train_l)
    warmup_scheduler = WarmUpLR(optimizer, iter_per_epoch * args.warm)

    if args.resume:
        recent_folder = most_recent_folder(os.path.join(settings.CHECKPOINT_PATH, args.net), fmt=settings.DATE_FORMAT)
        if not recent_folder:
            raise Exception('no recent folder were found')
        # 这里需要哦改为“vgg16”
        checkpoint_path = os.path.join(settings.CHECKPOINT_PATH, 'vgg16', recent_folder)
    # 这里需要哦改为“vgg16”
    else:
        checkpoint_path = os.path.join(settings.CHECKPOINT_PATH, 'vgg16', settings.TIME_NOW)

    # create checkpoint folder to save model
    if not os.path.exists(checkpoint_path):
        os.makedirs(checkpoint_path)
    checkpoint_path = os.path.join(checkpoint_path, '{net}-{epoch}-{type}.pth')

    best_acc = 0.0
    best_acc2 = 0.0
    if args.resume:
        best_weights = best_acc_weights(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))
        if best_weights:
            weights_path = os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder, best_weights)
            print('found best acc weights file:{}'.format(weights_path))
            print('load best training file to test acc...')
            net.load_state_dict(torch.load(weights_path))
            best_acc = eval_training(tb=False)
            print('best acc is {:0.2f}'.format(best_acc))

        recent_weights_file = most_recent_weights(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))
        if not recent_weights_file:
            raise Exception('no recent weights file were found')
        weights_path = os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder, recent_weights_file)
        print('loading weights file {} to resume training.....'.format(weights_path))
        net.load_state_dict(torch.load(weights_path))

        resume_epoch = last_epoch(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))

    for epoch in range(1, settings.EPOCH + 1):
        if epoch > args.warm:
            train_scheduler.step(epoch)

        if args.resume:
            if epoch <= resume_epoch:
                continue

        train(epoch)
        acc = eval_training(epoch)
        # 这里需要哦改为“vgg16”
        # start to save best performance model after learning rate decay to 0.01
        if epoch <= settings.MILESTONES[3] and best_acc < acc:
            weights_path = checkpoint_path.format(net='vgg16', epoch=epoch, type='best')
            weights_path3 = checkpoint_path.format(net='net3', epoch=epoch, type='best')
            print('saving weights file to {}'.format(weights_path))
            torch.save(net.state_dict(), weights_path)
            torch.save(net3.state_dict(), weights_path3)
            best_acc = acc

            continue

    # 指定保存数据的文件夹路径
    # folder_path = folder_path
    # my_train_loss_cpu = [t.cpu().numpy() for t in my_train_loss]
    # my_eval_loss_cpu = [t.cpu().numpy() for t in my_eval_loss]
    # my_train_correct_cpu = [t.cpu().numpy() for t in my_train_correct]
    # my_eval_correct_cpu = [t.cpu().numpy() for t in my_eval_correct]

    # 保存 label 和 pro 到一个文件
    np.savez(os.path.join(folder_path, 'loss.npz'), my_train_loss=my_train_loss, my_eval_loss=my_eval_loss,
             my_train_correct=my_train_correct, my_eval_correct=my_eval_correct)
    print('my_train_loss:', len(my_train_loss))
    print('my_eval_loss:', len(my_eval_loss))
    print('my_train_correct:', my_train_correct)
    print('my_eval_correct:', my_eval_correct)



 单序列将两个网络融合到一起训练

注意修改完网络拼接在一起后,网络模型要添加到优化器optimizer中,还要添加net_vgg

.train(),net_vgg.eval(),还要将新的模型保存到路径中,在测试集中还要加载。

weights_path4 = checkpoint_path.format(net='net_vgg', epoch=epoch, type='best')
torch.save(net3.state_dict(), weights_path3)
import os

os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
import os
import sys
import argparse
import time
from datetime import datetime
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.nn import CosineEmbeddingLoss
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

# 需要修改“resnet50”
from models.resnet50 import *
from models.vgg import *
from conf import settings
from utils import get_network, WarmUpLR, \
    most_recent_folder, most_recent_weights, last_epoch, best_acc_weights
from dataset import CESM

# 指定保存数据的文件夹路径
folder_path = r'C:\Users\Raytrack\Desktop\CT'

my_train_loss = []
my_eval_loss = []
my_train_correct = []
my_eval_correct = []


def train(epoch):
    start = time.time()
    train_loss = 0.0  # cost function error
    correct = 0.0
    net.train()
    net3.train()
    net_vgg.train()
    p = 0
    for i, x in enumerate(CESM_10_train_l):
        low_energy = x['LOW_ENERGY']
        # high_energy = x['HIGH_ENERGY']
        # enhance = x['ENHANCE']

        labels = x['label']
        labels = torch.LongTensor(labels.numpy())
        # labels = torch.IntTensor(labels).to(torch.long)

        if args.gpu:
            low_energy = low_energy.to(device)
            # high_energy = high_energy.to(device)
            # enhance = enhance.to(device)
            labels = labels.to(device)

        optimizer.zero_grad()

        outputs_low_energy, ou_CCL = net(low_energy)


        # outputs_high_energy,ou_CCR = net(high_energy)
        # outputs_enhance,ou_MLOL = net(enhance)

        # outputs1 = torch.cat((outputs_low_energy  #, outputs_high_energy,outputs_enhance
        #                     ), dim=1)
        outputs_low_energy_vgg, ou_CCL = net_vgg(low_energy)



        outputs1 = torch.cat((outputs_low_energy, outputs_low_energy_vgg), dim=1)
        ou11 =  net3(outputs1)
        loss = loss_function(ou11, labels)
        print('loss:{}'.format(
            loss.item()
        )

        )

        loss.backward()
        optimizer.step()
        train_loss += loss.sum().item()
        _, preds = ou11.max(1)

        correct += preds.eq(labels).sum()
        n_iter = (epoch - 1) * len(CESM_10_train_l) + i + 1

        print('Training Epoch: {epoch} [{trained_samples}/{total_samples}]\t Train Loss: {:0.4f}\tLR: {:0.6f}'.format(
            loss.item(),
            optimizer.param_groups[0]['lr'],
            # correct.float() / len(CESMdata),
            epoch=epoch,
            trained_samples=i * args.b + len(low_energy),
            total_samples=len(CESMdata)
        ))

        if epoch <= args.warm:
            warmup_scheduler.step()

    train_loss_ = train_loss / (len(CESMdata))
    train_correct = correct / (len(CESMdata))
    my_train_loss.append(train_loss_)
    my_train_correct.append(train_correct.cpu())

    finish = time.time()

    print('epoch {} training time consumed: {:.2f}s'.format(epoch, finish - start))
    print('Train Average loss: {:.4f}\tTrain Accuarcy: {:0.6f}'.format(
        train_loss / len(CESMdata),
        correct.cpu() / (len(CESMdata))
    ))


@torch.no_grad()
def eval_training(epoch=0, tb=True):
    start = time.time()
    net.eval()
    net3.eval()
    net_vgg.eval()
    test_loss = 0.0  # cost function error
    correct = 0.0
    correct2 = 0.0

    for i, x in enumerate(CESM_10_test_l):

        low_energy = x['LOW_ENERGY']
        # high_energy = x['HIGH_ENERGY']
        # enhance = x['ENHANCE']

        labels = x['label']
        labels = torch.LongTensor(labels.numpy())
        # labels = torch.IntTensor(labels).to(torch.long)

        if args.gpu:
            low_energy = low_energy.to(device)
            # high_energy = high_energy.to(device)
            # enhance = enhance.to(device)
            labels = labels.to(device)

        optimizer.zero_grad()
        outputs_low_energy, ou_CCL = net(low_energy)

        outputs_low_energy_vgg, ou_CCL = net_vgg(low_energy)
        # outputs_high_energy,ou_CCR = net(high_energy)
        # outputs_enhance,ou_MLOL = net(enhance)

        # outputs1 = torch.cat((outputs_low_energy#, outputs_high_energy,outputs_enhance
        #                      ), dim=1)

        outputs_low_energy, ou_CCL = net(low_energy)


        # outputs_high_energy,ou_CCR = net(high_energy)
        # outputs_enhance,ou_MLOL = net(enhance)

        # outputs1 = torch.cat((outputs_low_energy  #, outputs_high_energy,outputs_enhance
        #                     ), dim=1)
        outputs_low_energy_vgg, ou_CCL = net_vgg(low_energy)



        outputs1 = torch.cat((outputs_low_energy, outputs_low_energy_vgg), dim=1)
        ou11 =  net3(outputs1)
        loss = loss_function(ou11, labels)

        n_iter = (epoch - 1) * len(CESM_10_test_l) + i + 1
        test_loss += loss.sum().item()
        _, preds = ou11.max(1)
        correct += preds.eq(labels).sum()

    test_loss_ = test_loss / (len(CESMdata2))
    my_eval_loss.append(test_loss_)
    eval_correct = correct / (len(CESMdata2))
    my_eval_correct.append(eval_correct.cpu())

    finish = time.time()

    if args.gpu:
        print('GPU INFO.....')
        print(torch.cuda.memory_summary(), end='')
    print('Evaluating Network.....')
    print('Eval set: Epoch: {},Eval Average loss: {:.4f},Eval Accuracy: {:.4f} Time consumed:{:.2f}s'.format(
        epoch,
        test_loss / len(CESMdata2),
        correct.cpu() / (len(CESMdata2)),
        finish - start
    ))
    print()

    # 需要修改保存每一轮的损失和正确率到loss1中
    np.savez(os.path.join(folder_path, 'loss1.npz'), my_train_loss=my_train_loss, my_eval_loss=my_eval_loss,
             my_train_correct=my_train_correct, my_eval_correct=my_eval_correct)

    return correct.cpu() / (len(CESMdata2))


if __name__ == '__main__':
    # 共需要修改四处,加上导入模型为五处
    parser = argparse.ArgumentParser()
    # parser.add_argument('-net', type=str, required=True, help='net type')
    parser.add_argument('-gpu', action='store_true', default=True, help='use gpu or not')
    parser.add_argument('-b', type=int, default=10, help='batch size for dataloader')
    parser.add_argument('-warm', type=int, default=0, help='warm up training phase')
    parser.add_argument('-lr', type=float, default=0.001, help='initial learning rate')
    parser.add_argument('-resume', action='store_true', default=False, help='resume training')
    args = parser.parse_args()
    
    # 检查是否有可用的 CUDA 设备,如果没有,则使用 CPU
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    if device.type == "cuda":
        print("Device GPUid:{} is available".format(torch.cuda.current_device()))
    else:
        print("CUDA is not available, using CPU for training.")

    # 需要修改“resnet50”
    net = CustomResNet50(in_channels=1, num_classes=2)

    net = net.to(device)

    net_vgg = vgg16_bn()
    net_vgg =net_vgg.to(device)

    # path1 = 'pretrained models'
    # net.load_state_dict(torch.load(path1),strict=False)
    net3 = nn.Linear(2048+512, 2)
    net3.to(device)

    # net3_vgg = nn.Linear(512*2, 2)
    # net3_vgg.cuda()

    CESMdata = CESM(base_dir=r"C:\Users\Raytrack\Documents\CR的最后数据集代码\MF\CR的均值化数据\train",
                    transform=transforms.Compose([
                        # Random表示有可能做,所以也可能不做
                        transforms.RandomHorizontalFlip(p=0.5),  # 水平翻转
                        transforms.RandomVerticalFlip(p=0.5),  # 上下翻转
                        transforms.RandomRotation(10),  # 随机旋转-10°~10°
                        # transforms.RandomRotation([90, 180]), # 随机在90°、180°中选一个度数来旋转,如果想有一定概率不旋转,可以加一个0进去
                        # transforms.ColorJitter(brightness=0.3, contrast=0.3, hue=0.3)
                        # transforms.Normalize(0, 1)
                        transforms.ToTensor(),

                    ]))
    CESM_10_train_l = DataLoader(CESMdata, batch_size=args.b, shuffle=True, drop_last=False,
                                 pin_memory=torch.cuda.is_available())

    CESMdata2 = CESM(base_dir=r"C:\Users\Raytrack\Documents\CR的最后数据集代码\MF\CR的均值化数据\valid",
                     transform=transforms.Compose([
                         transforms.ToTensor(),
                     ]))
    CESM_10_test_l = DataLoader(CESMdata2, batch_size=args.b, shuffle=False, drop_last=False,
                                pin_memory=torch.cuda.is_available())

    loss_function = nn.CrossEntropyLoss()
    loss_function.to(device)

    optimizer = optim.SGD([{"params": net.parameters()}, {"params": net3.parameters()}, {"params": net_vgg.parameters()}], lr=args.lr, momentum=0.9,
                          weight_decay=5e-4)
    train_scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=settings.MILESTONES,
                                                     gamma=0.5)  # learning rate decay
    iter_per_epoch = len(CESM_10_train_l)
    warmup_scheduler = WarmUpLR(optimizer, iter_per_epoch * args.warm)

    if args.resume:
        recent_folder = most_recent_folder(os.path.join(settings.CHECKPOINT_PATH, args.net), fmt=settings.DATE_FORMAT)
        if not recent_folder:
            raise Exception('no recent folder were found')
        # 需要修改“resnet50”
        checkpoint_path = os.path.join(settings.CHECKPOINT_PATH,'vgg+resnet50', recent_folder)
    # 需要修改“resnet50”
    else:
        checkpoint_path = os.path.join(settings.CHECKPOINT_PATH, 'vgg+resnet50', settings.TIME_NOW)

    # create checkpoint folder to save model
    if not os.path.exists(checkpoint_path):
        os.makedirs(checkpoint_path)
    checkpoint_path = os.path.join(checkpoint_path, '{net}-{epoch}-{type}.pth')

    best_acc = 0.0
    best_acc2 = 0.0
    if args.resume:
        best_weights = best_acc_weights(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))
        if best_weights:
            weights_path = os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder, best_weights)
            print('found best acc weights file:{}'.format(weights_path))
            print('load best training file to test acc...')
            net.load_state_dict(torch.load(weights_path))
            best_acc = eval_training(tb=False)
            print('best acc is {:0.2f}'.format(best_acc))

        recent_weights_file = most_recent_weights(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))
        if not recent_weights_file:
            raise Exception('no recent weights file were found')
        weights_path = os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder, recent_weights_file)
        print('loading weights file {} to resume training.....'.format(weights_path))
        net.load_state_dict(torch.load(weights_path))

        resume_epoch = last_epoch(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))

    for epoch in range(1, settings.EPOCH + 1):
        if epoch > args.warm:
            train_scheduler.step(epoch)

        if args.resume:
            if epoch <= resume_epoch:
                continue

        train(epoch)
        acc = eval_training(epoch)
        # 需要修改“resnet50”
        # start to save best performance model after learning rate decay to 0.01
        if epoch <= settings.MILESTONES[3] and best_acc < acc:
            weights_path = checkpoint_path.format(net='vgg+resnet50', epoch=epoch, type='best')
            weights_path3 = checkpoint_path.format(net='net3', epoch=epoch, type='best')
            weights_path4 = checkpoint_path.format(net='net_vgg', epoch=epoch, type='best')
            print('saving weights file to {}'.format(weights_path))
            torch.save(net.state_dict(), weights_path)
            torch.save(net3.state_dict(), weights_path3)
            torch.save(net_vgg.state_dict(), weights_path4)
            best_acc = acc

            continue

    # 保存 label 和 pro 到一个文件
    np.savez(os.path.join(folder_path, 'loss.npz'), my_train_loss=my_train_loss, my_eval_loss=my_eval_loss,
             my_train_correct=my_train_correct, my_eval_correct=my_eval_correct)
    print('my_train_loss:', len(my_train_loss))
    print('my_eval_loss:', len(my_eval_loss))
    print('my_train_correct:', my_train_correct)
    print('my_eval_correct:', my_eval_correct)

 多序列将两个神经网络融合进行训练

这个需要于单序列的代码有要结合着单序列改动

import os
import sys
import argparse
import time
from datetime import datetime

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.nn import CosineEmbeddingLoss

from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

# 需要改为Vgg
from models.resnet18 import *
from models.vgg import *
from conf import settings
from utils import get_network, WarmUpLR, \
    most_recent_folder, most_recent_weights, last_epoch, best_acc_weights
from dataset import CESM

# 指定保存数据的文件夹路径
folder_path = r'C:\Users\Raytrack\Desktop\MR'

my_train_loss = []
my_eval_loss = []
my_train_correct = []
my_eval_correct = []


def train(epoch):
    start = time.time()
    train_loss = 0.0  # cost function error
    correct = 0.0
    net.train()
    net3.train()
    net_vgg.train()
    p = 0
    for i, x in enumerate(CESM_10_train_l):
        low_energy = x['LOW_ENERGY']
        high_energy = x['HIGH_ENERGY']
        enhance = x['ENHANCE']

        labels = x['label']
        labels = torch.LongTensor(labels.numpy())
        # labels = torch.IntTensor(labels).to(torch.long)

        if args.gpu:
            low_energy = low_energy.to(device)
            high_energy = high_energy.to(device)
            enhance = enhance.to(device)
            labels = labels.to(device)

        optimizer.zero_grad()
        outputs_low_energy, ou_CCL = net(low_energy)
        outputs_high_energy, ou_CCR = net(high_energy)
        outputs_enhance, ou_MLOL = net(enhance)


        outputs_low_energy_vgg, ou_CCL = net_vgg(low_energy)
        outputs_high_energy_vgg, ou_CCR = net_vgg(high_energy)
        outputs_enhance_vgg, ou_MLOL = net_vgg(enhance)


        outputs1 = torch.cat((outputs_low_energy, outputs_high_energy, outputs_enhance,outputs_low_energy_vgg,outputs_high_energy_vgg,outputs_enhance_vgg), dim=1)

        ou11 = net3(outputs1)
        loss = loss_function(ou11, labels)
        print('loss:{}'.format(
            loss.item()
        )

        )

        loss.backward()
        optimizer.step()
        train_loss += loss.item()
        _, preds = ou11.max(1)

        correct += preds.eq(labels).sum()
        n_iter = (epoch - 1) * len(CESM_10_train_l) + i + 1

        print('Training Epoch: {epoch} [{trained_samples}/{total_samples}]\tLoss: {:0.4f}\tLR: {:0.6f}'.format(
            loss.item(),
            optimizer.param_groups[0]['lr'],
            # correct.float() / len(CESMdata),
            epoch=epoch,
            trained_samples=i * args.b + len(low_energy),
            total_samples=len(CESMdata)
        ))

        if epoch <= args.warm:
            warmup_scheduler.step()

    train_loss_ = train_loss / (len(CESMdata))
    train_correct = correct / (len(CESMdata))
    my_train_loss.append(train_loss_)
    my_train_correct.append(train_correct.cpu())

    finish = time.time()

    print('epoch {} training time consumed: {:.2f}s'.format(epoch, finish - start))
    print('Train Average loss: {:.4f}\tTrain Accuarcy: {:0.6f}'.format(
        train_loss / len(CESMdata),
        correct.cpu() / (len(CESMdata))
    ))


@torch.no_grad()
def eval_training(epoch=0, tb=True):
    start = time.time()
    net.eval()
    net3.eval()
    net_vgg.eval()
    test_loss = 0.0  # cost function error
    correct = 0.0
    correct2 = 0.0

    for i, x in enumerate(CESM_10_test_l):

        low_energy = x['LOW_ENERGY']
        high_energy = x['HIGH_ENERGY']
        enhance = x['ENHANCE']

        labels = x['label']
        labels = torch.LongTensor(labels.numpy())
        # labels = torch.IntTensor(labels).to(torch.long)

        if args.gpu:
            low_energy = low_energy.to(device)
            high_energy = high_energy.to(device)
            enhance = enhance.to(device)
            labels = labels.to(device)

        optimizer.zero_grad()
        outputs_low_energy, ou_CCL = net(low_energy)
        outputs_high_energy, ou_CCR = net(high_energy)
        outputs_enhance, ou_MLOL = net(enhance)

        outputs_low_energy_vgg, ou_CCL = net_vgg(low_energy)
        outputs_high_energy_vgg, ou_CCR = net_vgg(high_energy)
        outputs_enhance_vgg, ou_MLOL = net_vgg(enhance)

        outputs1 = torch.cat((outputs_low_energy, outputs_high_energy, outputs_enhance,outputs_low_energy_vgg,outputs_high_energy_vgg,outputs_enhance_vgg), dim=1)

        ou11 = net3(outputs1)
        loss = loss_function(ou11, labels)

        n_iter = (epoch - 1) * len(CESM_10_test_l) + i + 1
        test_loss += loss.item()
        _, preds = ou11.max(1)
        correct += preds.eq(labels).sum()

    test_loss_ = test_loss / (len(CESMdata2))
    my_eval_loss.append(test_loss_)
    eval_correct = correct / (len(CESMdata2))
    my_eval_correct.append(eval_correct.cpu())

    finish = time.time()

    if args.gpu:
        print('GPU INFO.....')
        print(torch.cuda.memory_summary(), end='')
    print('Evaluating Network.....')
    print('Eval set: Epoch: {},Eval Average loss: {:.4f},Eval Accuracy: {:.4f} Time consumed:{:.2f}s'.format(
        epoch,
        test_loss / len(CESMdata2),
        correct.cpu() / (len(CESMdata2)),
        finish - start
    ))
    print()
    # 需要修改保存每一轮的损失和正确率到loss1中
    np.savez(os.path.join(folder_path, 'loss1.npz'), my_train_loss=my_train_loss, my_eval_loss=my_eval_loss,
             my_train_correct=my_train_correct, my_eval_correct=my_eval_correct)

    return correct.cpu() / (len(CESMdata2))


if __name__ == '__main__':
    # 一共要改4处“vgg16”,再加一次导入模型共修改5个地方
    parser = argparse.ArgumentParser()
    # parser.add_argument('-net', type=str,default='ResNet50', required=True, help='net type')
    parser.add_argument('-gpu', action='store_true', default=True, help='use gpu or not')
    parser.add_argument('-b', type=int, default=8, help='batch size for dataloader')
    parser.add_argument('-warm', type=int, default=0, help='warm up training phase')
    parser.add_argument('-lr', type=float, default=0.001, help='initial learning rate')
    parser.add_argument('-resume', action='store_true', default=False, help='resume training')
    args = parser.parse_args()
    
    # 检查是否有可用的 CUDA 设备,如果没有,则使用 CPU
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    if device.type == "cuda":
        print("Device GPUid:{} is available".format(torch.cuda.current_device()))
    else:
        print("CUDA is not available, using CPU for training.")

    
    # 这里需要哦改为“vgg16”
    net = CustomResNet18(in_channels=1, num_classes=2)
    net = net.to(device)

    net_vgg = vgg16_bn()
    net_vgg =net_vgg.to(device)
    # path1 = 'pretrained models'
    # net.load_state_dict(torch.load(path1),strict=False)
    net3 = nn.Linear(512 * 6, 2)
    net3.to(device)

    CESMdata = CESM(base_dir=r'C:\Users\Raytrack\Documents\325例乳腺癌数据代码\MF\h5py\train',
                    transform=transforms.Compose([
                        # Random表示有可能做,所以也可能不做
                        transforms.RandomHorizontalFlip(p=0.5),  # 水平翻转
                        transforms.RandomVerticalFlip(p=0.5),  # 上下翻转
                        transforms.RandomRotation(10),  # 随机旋转-10°~10°
                        # transforms.RandomRotation([90, 180]), # 随机在90°、180°中选一个度数来旋转,如果想有一定概率不旋转,可以加一个0进去
                        # transforms.ColorJitter(brightness=0.3, contrast=0.3, hue=0.3)
                        # transforms.Normalize(0, 1)
                        transforms.ToTensor(),

                    ]))
    CESM_10_train_l = DataLoader(CESMdata, batch_size=args.b, shuffle=True, drop_last=False,
                                 pin_memory=torch.cuda.is_available())

    CESMdata2 = CESM(base_dir=r'C:\Users\Raytrack\Documents\325例乳腺癌数据代码\MF\h5py\valid',
                     transform=transforms.Compose([
                         transforms.ToTensor(),
                     ]))
    CESM_10_test_l = DataLoader(CESMdata2, batch_size=args.b, shuffle=False, drop_last=False,
                                pin_memory=torch.cuda.is_available())

    loss_function = nn.CrossEntropyLoss()
    loss_function.to(device)

    optimizer = optim.SGD([{"params": net.parameters()}, {"params": net3.parameters()}, {"params": net_vgg.parameters()}], lr=args.lr, momentum=0.9,
                          weight_decay=5e-4)
    train_scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=settings.MILESTONES,
                                                     gamma=0.5)  # learning rate decay
    iter_per_epoch = len(CESM_10_train_l)
    warmup_scheduler = WarmUpLR(optimizer, iter_per_epoch * args.warm)

    if args.resume:
        recent_folder = most_recent_folder(os.path.join(settings.CHECKPOINT_PATH, args.net), fmt=settings.DATE_FORMAT)
        if not recent_folder:
            raise Exception('no recent folder were found')
        # 这里需要哦改为“vgg16”
        checkpoint_path = os.path.join(settings.CHECKPOINT_PATH, 'vgg+resnet18', recent_folder)
    # 这里需要哦改为“vgg16”
    else:
        checkpoint_path = os.path.join(settings.CHECKPOINT_PATH, 'vgg+resnet18', settings.TIME_NOW)

    # create checkpoint folder to save model
    if not os.path.exists(checkpoint_path):
        os.makedirs(checkpoint_path)
    checkpoint_path = os.path.join(checkpoint_path, '{net}-{epoch}-{type}.pth')

    best_acc = 0.0
    best_acc2 = 0.0
    if args.resume:
        best_weights = best_acc_weights(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))
        if best_weights:
            weights_path = os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder, best_weights)
            print('found best acc weights file:{}'.format(weights_path))
            print('load best training file to test acc...')
            net.load_state_dict(torch.load(weights_path))
            best_acc = eval_training(tb=False)
            print('best acc is {:0.2f}'.format(best_acc))

        recent_weights_file = most_recent_weights(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))
        if not recent_weights_file:
            raise Exception('no recent weights file were found')
        weights_path = os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder, recent_weights_file)
        print('loading weights file {} to resume training.....'.format(weights_path))
        net.load_state_dict(torch.load(weights_path))

        resume_epoch = last_epoch(os.path.join(settings.CHECKPOINT_PATH, args.net, recent_folder))

    for epoch in range(1, settings.EPOCH + 1):
        if epoch > args.warm:
            train_scheduler.step(epoch)

        if args.resume:
            if epoch <= resume_epoch:
                continue

        train(epoch)
        acc = eval_training(epoch)
        # 这里需要哦改为“vgg16”
        # start to save best performance model after learning rate decay to 0.01
        if epoch <= settings.MILESTONES[3] and best_acc < acc:
            weights_path = checkpoint_path.format(net='resnet18', epoch=epoch, type='best')
            weights_path3 = checkpoint_path.format(net='net3', epoch=epoch, type='best')
            weights_path4 = checkpoint_path.format(net='net_vgg', epoch=epoch, type='best')
            print('saving weights file to {}'.format(weights_path))
            torch.save(net.state_dict(), weights_path)
            torch.save(net3.state_dict(), weights_path3)
            torch.save(net_vgg.state_dict(), weights_path4)
            best_acc = acc

            continue

    # 指定保存数据的文件夹路径
    # folder_path = folder_path

    # 保存 label 和 pro 到一个文件
    np.savez(os.path.join(folder_path, 'loss.npz'), my_train_loss=my_train_loss, my_eval_loss=my_eval_loss,
             my_train_correct=my_train_correct, my_eval_correct=my_eval_correct)
    print('my_train_loss:', len(my_train_loss))
    print('my_eval_loss:', len(my_eval_loss))
    print('my_train_correct:', my_train_correct)
    print('my_eval_correct:', my_eval_correct)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值