基于IV曲线数据的光伏故障智能诊断(PyTorch)

本文代码和数据地址: https://github.com/shanglianlm0525/TimeSeries

注意:代码和数据仅供学习使用,不能用于商用目的,违法必究。

1 数据

数据来自自有采集部分数据,分为正常和故障两个类别,其中 train:1398,val:350。

加载数据类

class IVDataset(Dataset):
    def __init__(self, root_path='', stage='train', input_size=100, p=0.8):
        super(IVDataset, self).__init__()
        self.root_path = root_path
        self.stage = stage
        self.input_size = input_size
        self.items = []
        self.labels = []
        self.names = []

        with open(self.root_path, 'rb') as f:
            iv_data = pickle.load(f)

        if self.stage == 'test':
            for k, v in iv_data.items():
                self.items.append(np.array([v['pvv'], v['pvi']]))  # 2*100
        else:
            for k, v in iv_data.items():
                self.items.append(np.array([v['pvv'], v['pvi']])) # 2*100
                self.labels.append(v['lbl'])
        print('{} :datasets: {}'.format(self.stage, len(self.items)))


    def __getitem__(self, idx):
        item = self.items[idx]

        if self.stage == "train":
            item = torch.from_numpy(item)
            return item, self.labels[idx]
        else:
            item = torch.from_numpy(item)
            if self.stage == "test":
                return item
            else:
                return item, self.labels[idx]

    def __len__(self):
        return self.items.__len__()

2 模型

模型主要基于 shufflenet_v2改造,将Conv2d, BatchNorm2d, channel_shuffle2d 改为 Conv1d, BatchNorm1d, channel_shuffle1d,输入为 N * 2 * 100, 输出为 N * 2。

class IVModel(nn.Module):
    def __init__(self, inp=2, oup=2):
        super(IVModel,self).__init__()
        blocks = [2, 4, 2]
        channels =[12, 24, 48, 96, 196]
        self.stem = nn.Sequential(
            nn.Conv1d(inp, channels[0], 3, 2, 1, bias=False),
            nn.BatchNorm1d(channels[0]),
            nn.ReLU(inplace=True)
        )
        self.maxpool = nn.MaxPool1d(kernel_size=3, stride=2, padding=1)

        # Static annotations for mypy
        self.stage2: nn.Sequential
        self.stage3: nn.Sequential
        self.stage4: nn.Sequential
        stage_names = [f"stage{i}" for i in [2, 3, 4]]
        for i, (name, block) in enumerate(zip(stage_names, blocks)):
            seq = [InvertedResidual1D(channels[i], channels[i+1], 2)]
            for _ in range(block - 1):
                seq.append(InvertedResidual1D(channels[i+1], channels[i+1], 1))
            setattr(self, name, nn.Sequential(*seq))

        self.lastconv = nn.Sequential(
            nn.Conv1d(channels[3], channels[4], 1, 1, 0, bias=False),
            nn.BatchNorm1d(channels[4]),
            nn.ReLU(inplace=True)
        )

        self.fc = nn.Linear(channels[4], oup)

    def forward(self, x):
        x = self.stem(x)
        x = self.maxpool(x)
        x = self.stage2(x)
        x = self.stage3(x)
        x = self.stage4(x)
        x = self.lastconv(x)
        x = x.mean([2])  # globalpool
        x = self.fc(x)
        return x
'''
model = IVModel()
print(model)
input = torch.randn(1, 2, 100)
out = model(input)
'''

3 训练

训练代码:

class TrainIVcurve():
    def __init__(self):
        super(TrainIVcurve, self).__init__()
        self.data_dir = {'train':'iv_data_train.txt', 'val':'iv_data_val.txt'}
        # self.data_dir = {'train':'iv_data.txt', 'val':'iv_data.txt'}
        self.pretrain_model_path = f'weights/iv_data_weight.pth'
        self.save_model_path = f'weights/iv_data_weight.pth'
        self.input_size = 100 # length
        self.output_num = 2

        self.batch_size = 64
        self.num_epochs = 500  #
        self.init_lr = 0.01  # [0.1 0.01 0.001 0.0001 0.00001 0.000001]0.01 0.001 0.0001
        self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")


    def run(self):
        image_datasets = {x: IVDataset(root_path=self.data_dir[x], stage=x, input_size=self.input_size) for x in ['train', 'val']}  # , x
        dataloaders = {x: DataLoader(image_datasets[x], batch_size=self.batch_size, shuffle=True if x == 'train' else False,
                          num_workers=8) for x in ['train', 'val']}
        dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}

        model_ft = IVModel()
        if self.pretrain_model_path is not None and os.path.exists(self.pretrain_model_path):
            pass
            # print('load pretrained model: ', self.pretrain_model_path)
            # model_ft.load_state_dict(torch.load(self.pretrain_model_path), strict=False)
        model_ft = model_ft.to(self.device)

        criterion = FocalLoss(class_num=self.output_num)
        criterion.cuda(self.device)

        # optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9) # , weight_decay=0.0005
        # lr_scheduler_ft = optim.lr_scheduler.CosineAnnealingLR(optimizer_ft, self.num_epochs, eta_min=1e-7, last_epoch=-1)

        optimizer_ft = optim.Adam(model_ft.parameters(), lr=0.001, betas=(0.995, 0.999)) # weight_decay=0.0005
        lr_scheduler_ft = None

        since = time.time()
        best_model_wts = copy.deepcopy(model_ft.state_dict())
        best_acc = 0.0
        preds_list = []
        gt_labels_list = []
        for epoch in range(self.num_epochs):
            print('Epoch {}/{}'.format(epoch, self.num_epochs - 1))
            print('-' * 50)
            preds_list.clear()
            gt_labels_list.clear()
            # Each epoch has a training and validation phase
            for phase in ['train', 'val']:
                if phase == 'train':
                    model_ft.train()  # Set model to training mode
                else:
                    model_ft.eval()  # Set model to evaluate mode
                    preds_list = []
                    gt_labels_list = []

                running_loss = 0.0
                running_corrects = 0

                # Iterate over data.
                for inputs, labels in dataloaders[phase]:
                    inputs = inputs.to(self.device)
                    labels = labels.to(self.device)

                    # zero the parameter gradients
                    optimizer_ft.zero_grad()

                    # forward
                    # track history if only in train
                    with torch.set_grad_enabled(phase == 'train'):
                        outputs = model_ft(inputs)
                        _, preds = torch.max(outputs, 1)

                        # loss = criterion(outputs, labels)
                        loss = criterion(outputs, labels, self.device)

                        # backward + optimize only if in training phase
                        if phase == 'train':
                            loss.backward()
                            optimizer_ft.step()
                            if lr_scheduler_ft is not None:
                                lr_scheduler_ft.step()
                    preds_list.extend(preds.cpu().detach().numpy().tolist())
                    gt_labels_list.extend(labels.data.cpu().detach().numpy().tolist())
                    # statistics
                    running_loss += loss.item() * inputs.size(0)
                    running_corrects += torch.sum(preds == labels.data)

                epoch_loss = running_loss / dataset_sizes[phase]
                epoch_acc = running_corrects.double() / dataset_sizes[phase]

                print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))

                # deep copy the model
                if phase == 'val' and epoch_acc > best_acc:
                    best_acc = epoch_acc
                    best_model_wts = copy.deepcopy(model_ft.state_dict())
            print('')

        time_elapsed = time.time() - since
        print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
        print('Best val Acc: {:4f}'.format(best_acc))

        # load best model weights
        model_ft.load_state_dict(best_model_wts)
        torch.save(model_ft.state_dict(), self.save_model_path)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mingo_敏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值