草庐IT

用CapsNets做电能质量扰动分类(2019-08-05)

南海金雕 2023-10-10 原文

        当下最热神经网络为CNN,2017年10月,深度学习之父Hinton发表《胶囊间的动态路由》(Capsule Networks),最近谷歌正式开源了Hinton胶囊理论代码,提出的胶囊神经网络。本文不涉及原理,只是站在巨人的肩膀人,尝试把胶囊网络应用与分类问题。

原理和代码的参考文献是:https://blog.csdn.net/weixin_40920290/article/details/82951826

其中,本文采用的数据集和以2019年3月CNN做电能质量分类的一样,可以去那个博文中下载数据集。这里只展示代码。需要提醒的是,Capsule Networks的运行速度会比较慢,耐心等待.

如果由于格式问题无法运行,可以把邮箱私戳发给我,我把Capsule.py发给你

1.代码

from __future__ import print_function

import numpy as np

from keras import layers, models, optimizers

from keras import backend as K

from keras.utils import to_categorical

import matplotlib.pyplot as plt

from utils import combine_images

from PIL import Image

from capsulelayers import CapsuleLayer, PrimaryCap, Length, Mask

import keras

from pandas import read_csv

K.set_image_data_format('channels_last')

def CapsNet(input_shape, n_class, routings):

    """

    A Capsule Network on MNIST.

    :param input_shape: data shape, 3d, [width, height, channels]

    :param n_class: number of classes

    :param routings: number of routing iterations

    :return: Two Keras Models, the first one used for training, and the second one for evaluation.

            `eval_model` can also be used for training.

    """

    x = layers.Input(shape=input_shape)

    # Layer 1: Just a conventional Conv2D layer

    conv1 = layers.Conv2D(filters=256, kernel_size=9, strides=1, padding='valid', activation='relu', name='conv1')(x)

    # Layer 2: Conv2D layer with `squash` activation, then reshape to [None, num_capsule, dim_capsule]

    primarycaps = PrimaryCap(conv1, dim_capsule=8, n_channels=32, kernel_size=9, strides=2, padding='valid')

    # Layer 3: Capsule layer. Routing algorithm works here.

    digitcaps = CapsuleLayer(num_capsule=n_class, dim_capsule=16, routings=routings,

                            name='digitcaps')(primarycaps)

    # Layer 4: This is an auxiliary layer to replace each capsule with its length. Just to match the true label's shape.

    # If using tensorflow, this will not be necessary. :)

    out_caps = Length(name='capsnet')(digitcaps)

    # Decoder network.

    y = layers.Input(shape=(n_class,))

    masked_by_y = Mask()([digitcaps, y])  # The true label is used to mask the output of capsule layer. For training

    masked = Mask()(digitcaps)  # Mask using the capsule with maximal length. For prediction

    # Shared Decoder model in training and prediction

    decoder = models.Sequential(name='decoder')

    decoder.add(layers.Dense(512, activation='relu', input_dim=16*n_class))

    decoder.add(layers.Dense(1024, activation='relu'))

    decoder.add(layers.Dense(np.prod(input_shape), activation='sigmoid'))

    decoder.add(layers.Reshape(target_shape=input_shape, name='out_recon'))

    # Models for training and evaluation (prediction)

    train_model = models.Model([x, y], [out_caps, decoder(masked_by_y)])

    eval_model = models.Model(x, [out_caps, decoder(masked)])

    # manipulate model

    noise = layers.Input(shape=(n_class, 16))

    noised_digitcaps = layers.Add()([digitcaps, noise])

    masked_noised_y = Mask()([noised_digitcaps, y])

    manipulate_model = models.Model([x, y, noise], decoder(masked_noised_y))

    return train_model, eval_model, manipulate_model

def margin_loss(y_true, y_pred):

    """

    Margin loss for Eq.(4). When y_true[i, :] contains not just one `1`, this loss should work too. Not test it.

    :param y_true: [None, n_classes]

    :param y_pred: [None, num_capsule]

    :return: a scalar loss value.

    """

    L = y_true * K.square(K.maximum(0., 0.9 - y_pred)) + \

        0.5 * (1 - y_true) * K.square(K.maximum(0., y_pred - 0.1))

    return K.mean(K.sum(L, 1))

def train(model, data, args):

    """

    Training a CapsuleNet

    :param model: the CapsuleNet model

    :param data: a tuple containing training and testing data, like `((x_train, y_train), (x_test, y_test))`

    :param args: arguments

    :return: The trained model

    """

    # unpacking the data

    (x_train, y_train), (x_test, y_test) = data

    # callbacks

    log = callbacks.CSVLogger(args.save_dir + '/log.csv')

    tb = callbacks.TensorBoard(log_dir=args.save_dir + '/tensorboard-logs',

                              batch_size=args.batch_size, histogram_freq=int(args.debug))

    checkpoint = callbacks.ModelCheckpoint(args.save_dir + '/weights-{epoch:02d}.h5', monitor='val_capsnet_acc',

                                          save_best_only=True, save_weights_only=True, verbose=1)

    lr_decay = callbacks.LearningRateScheduler(schedule=lambda epoch: args.lr * (args.lr_decay ** epoch))

    # compile the model

    model.compile(optimizer=optimizers.Adam(lr=args.lr),

                  loss=[margin_loss, 'mse'],

                  loss_weights=[1., args.lam_recon],

                  metrics={'capsnet': 'accuracy'})

    """

    # Training without data augmentation:

    model.fit([x_train, y_train], [y_train, x_train], batch_size=args.batch_size, epochs=args.epochs,

              validation_data=[[x_test, y_test], [y_test, x_test]], callbacks=[log, tb, checkpoint, lr_decay])

    """

    # Begin: Training with data augmentation ---------------------------------------------------------------------#

    def train_generator(x, y, batch_size, shift_fraction=0.):

        train_datagen = ImageDataGenerator(width_shift_range=shift_fraction,

                                          height_shift_range=shift_fraction)  # shift up to 2 pixel for MNIST

        generator = train_datagen.flow(x, y, batch_size=batch_size)

        while 1:

            x_batch, y_batch = generator.next()

            yield ([x_batch, y_batch], [y_batch, x_batch])

    # Training with data augmentation. If shift_fraction=0., also no augmentation.

    model.fit_generator(generator=train_generator(x_train, y_train, args.batch_size, args.shift_fraction),

                        steps_per_epoch=int(y_train.shape[0] / args.batch_size),

                        epochs=args.epochs,

                        validation_data=[[x_test, y_test], [y_test, x_test]],

                        callbacks=[log, tb, checkpoint, lr_decay])

    # End: Training with data augmentation -----------------------------------------------------------------------#

    model.save_weights(args.save_dir + '/trained_model.h5')

    print('Trained model saved to \'%s/trained_model.h5\'' % args.save_dir)

    from utils import plot_log

    plot_log(args.save_dir + '/log.csv', show=True)

    return model

def test(model, data, args):

    x_test, y_test = data

    y_pred, x_recon = model.predict(x_test, batch_size=100)

    print('-'*30 + 'Begin: test' + '-'*30)

    print('Test acc:', np.sum(np.argmax(y_pred, 1) == np.argmax(y_test, 1))/y_test.shape[0])

    img = combine_images(np.concatenate([x_test[:50],x_recon[:50]]))

    image = img * 255

    Image.fromarray(image.astype(np.uint8)).save(args.save_dir + "/real_and_recon.png")

    print()

    print('Reconstructed images are saved to %s/real_and_recon.png' % args.save_dir)

    print('-' * 30 + 'End: test' + '-' * 30)

    plt.imshow(plt.imread(args.save_dir + "/real_and_recon.png"))

    plt.show()

def manipulate_latent(model, data, args):

    print('-'*30 + 'Begin: manipulate' + '-'*30)

    x_test, y_test = data

    index = np.argmax(y_test, 1) == args.digit

    number = np.random.randint(low=0, high=sum(index) - 1)

    x, y = x_test[index][number], y_test[index][number]

    x, y = np.expand_dims(x, 0), np.expand_dims(y, 0)

    noise = np.zeros([1, 10, 16])

    x_recons = []

    for dim in range(16):

        for r in [-0.25, -0.2, -0.15, -0.1, -0.05, 0, 0.05, 0.1, 0.15, 0.2, 0.25]:

            tmp = np.copy(noise)

            tmp[:,:,dim] = r

            x_recon = model.predict([x, y, tmp])

            x_recons.append(x_recon)

    x_recons = np.concatenate(x_recons)

    img = combine_images(x_recons, height=16)

    image = img*255

    Image.fromarray(image.astype(np.uint8)).save(args.save_dir + '/manipulate-%d.png' % args.digit)

    print('manipulated result saved to %s/manipulate-%d.png' % (args.save_dir, args.digit))

    print('-' * 30 + 'End: manipulate' + '-' * 30)

def load_mnist():

    # the data, shuffled and split between train and test sets

    dataset = read_csv('ZerosOnePowerQuality.csv')

    values = dataset.values

    XY= values

    num_classes = 8

    Y = XY[:,784]

    n_train_hours1 =9000

    x_train=XY[:n_train_hours1,0:784]

    trainY =Y[:n_train_hours1]

    x_test =XY[n_train_hours1:, 0:784]

    testY =Y[n_train_hours1:]

    x_train = x_train.reshape(-1,28,28,1)

    x_test = x_test.reshape(-1,28,28,1)

    y_train = keras.utils.to_categorical(trainY, num_classes)

    y_test = keras.utils.to_categorical(testY, num_classes)

    return (x_train, y_train), (x_test, y_test)

if __name__ == "__main__":

    import os

    import argparse

    from keras.preprocessing.image import ImageDataGenerator

    from keras import callbacks

    # setting the hyper parameters

    parser = argparse.ArgumentParser(description="Capsule Network on MNIST.")

    parser.add_argument('--epochs', default=50, type=int)

    parser.add_argument('--batch_size', default=100, type=int)

    parser.add_argument('--lr', default=0.001, type=float,

                        help="Initial learning rate")

    parser.add_argument('--lr_decay', default=0.9, type=float,

                        help="The value multiplied by lr at each epoch. Set a larger value for larger epochs")

    parser.add_argument('--lam_recon', default=0.392, type=float,

                        help="The coefficient for the loss of decoder")

    parser.add_argument('-r', '--routings', default=3, type=int,

                        help="Number of iterations used in routing algorithm. should > 0")

    parser.add_argument('--shift_fraction', default=0.1, type=float,

                        help="Fraction of pixels to shift at most in each direction.")

    parser.add_argument('--debug', action='store_true',

                        help="Save weights by TensorBoard")

    parser.add_argument('--save_dir', default='./result')

    parser.add_argument('-t', '--testing', action='store_true',

                        help="Test the trained model on testing dataset")

    parser.add_argument('--digit', default=5, type=int,

                        help="Digit to manipulate")

    parser.add_argument('-w', '--weights', default=None,

                        help="The path of the saved weights. Should be specified when testing")

    args = parser.parse_args()

    print(args)

    if not os.path.exists(args.save_dir):

        os.makedirs(args.save_dir)

    # load data

    (x_train, y_train), (x_test, y_test) = load_mnist()

    # define model

    model, eval_model, manipulate_model = CapsNet(input_shape=x_train.shape[1:],

                                                  n_class=len(np.unique(np.argmax(y_train, 1))),

                                                  routings=args.routings)

    model.summary()

    # train or test

    if args.weights is not None:  # init the model weights with provided one

        model.load_weights(args.weights)

    if not args.testing:

        train(model=model, data=((x_train, y_train), (x_test, y_test)), args=args)

    else:  # as long as weights are given, will run testing

        if args.weights is None:

            print('No weights are provided. Will test using random initialized weights.')

        manipulate_latent(manipulate_model, (x_test, y_test), args)

        test(model=eval_model, data=(x_test, y_test), args=args)


2.网络结构

Layer (type) Output Shape Param # Connected to

==================================================================================================

input_1 (InputLayer)            (None, 28, 28, 1)    0                                           

__________________________________________________________________________________________________

conv1 (Conv2D)                  (None, 20, 20, 256)  20992      input_1[0][0]                   

__________________________________________________________________________________________________

primarycap_conv2d (Conv2D)      (None, 6, 6, 256)    5308672    conv1[0][0]                     

__________________________________________________________________________________________________

primarycap_reshape (Reshape)    (None, 1152, 8)      0          primarycap_conv2d[0][0]         

__________________________________________________________________________________________________

primarycap_squash (Lambda)      (None, 1152, 8)      0          primarycap_reshape[0][0]       

__________________________________________________________________________________________________

digitcaps (CapsuleLayer)        (None, 8, 16)        1179648    primarycap_squash[0][0]         

__________________________________________________________________________________________________

input_2 (InputLayer)            (None, 8)            0                                           

__________________________________________________________________________________________________

mask_1 (Mask)                  (None, 128)          0          digitcaps[0][0]                 

                                                                input_2[0][0]                   

__________________________________________________________________________________________________

capsnet (Length)                (None, 8)            0          digitcaps[0][0]                 

__________________________________________________________________________________________________

decoder (Sequential)            (None, 28, 28, 1)    1394960    mask_1[0][0]                   

==================================================================================================

Total params: 7,904,272

Trainable params: 7,904,272

Non-trainable params: 0

____________________________

有关用CapsNets做电能质量扰动分类(2019-08-05)的更多相关文章

  1. iOS适配Unity-2019 - 2

    iOS适配Unity-2019背景由于2019起,Unity的Xcode工程,更改了项目结构。Unity2018的结构:可以看Targets只有一个Unity-iPhone,Unity-iPhone直接依赖管理三方库。Unity2019以后:Targets多了一个UnityFramework,UnityFramework管理三方库,Unity-iPhone依赖于UnityFramwork。所以升级后,会有若干的问题,以下是对问题的解决方式。问题一错误描述error:exportArchive:Missingsigningidentifierat"/var/folders/fr//T/Xcode

  2. ruby-on-rails - 如何使用 Paperclip 降低上传图像的质量? - 2

    我正在运行RubyonRails3,我想使用Paperclip插件/gem降低上传图像的质量。我该怎么做?此时在我的模型文件中我有:has_attached_file:avatar,:styles=>{:thumb=>["50x50#",:jpg],:medium=>["250x250#",:jpg],:original=>["600x600#",:jpg]}这会将图像转换为.jpg格式并设置尺寸。 最佳答案 尝试使用convert_options。has_attached_file:avatar,:styles=>{:thumb=

  3. ruby-on-rails - 带有分类器 gem 的无效编码符号 - 2

    当我将项目添加到我的Postgres数据库时,一切似乎都运行良好。在不做任何更改的情况下,只要在我的应用程序中的任何位置启动Madeleine,我的Rails应用程序就会开始失败:EncodingErrorinEventsController#updateinvalidencodingsymbolapp/controllers/events_controller.rb:137:in`update'137是问题行:135defupdate136@event=Event.find(params[:id])137m=SnapshotMadeleine.new("bayes_data")...

  4. AT24C04、AT24C08、AT24C16系列EEPROM芯片单片机读写驱动程序 - 2

    一、概述在之前的一篇博文中,记录了AT24C01、AT24C02芯片的读写驱动,先将之前的相关文章include一下:1.IIC驱动:4位数码管显示模块TM1637芯片C语言驱动程序2.AT24C01/AT24C02读写:AT24C01/AT24C02系列EEPROM芯片单片机读写驱动程序本文记录分享AT24C04、AT24C08、AT24C16芯片的单片机C语言读写驱动程序。二、芯片对比介绍型号容量bit容量byte页数字节/页器件寻址位可寻址器件数WordAddress位数/字节数备注AT24C044k5123216A2A149/1WordAddress使用P0位AT24C088k1024

  5. ruby - 贝叶斯分类器分数代表什么? - 2

    我正在使用rubyclassifiergem其分类方法返回根据训练模型分类的给定字符串的分数。分数是百分比吗?如果有,最大差值是100分吗? 最佳答案 这是概率的对数。对于大型训练集,实际概率是非常小的数字,因此对数更容易比较。从理论上讲,分数的范围从接近零的无穷小到负无穷大。10**score*100.0会给出实际概率,确实最大相差100。 关于ruby-贝叶斯分类器分数代表什么?,我们在StackOverflow上找到一个类似的问题: https://st

  6. ruby-on-rails - 虚拟属性和质量赋值 - 2

    开发者!我无法理解接下来的情况例如我有模型classPg::City我可以使用这样的代码:c=Pg::City.new({:population=>1000})putsc.population1000但是如果我取消注释上面的attr_accessible代码会抛出警告WARNING:Can'tmass-assignprotectedattributes:population如何将虚拟属性与模型属性一起用于质量分配?谢谢! 最佳答案 使用attr_accessor添加变量不会自动将其添加到attr_accessible。如果您要使用a

  7. Ruby 核心文档质量 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭4年前。Improvethisquestion我是Ruby的新手,时间有限,因此我尝试了一些简单的东西。最近我需要创建一个文件,因为我太懒了,所以我跑去谷歌。结果:File.open(local_filename,'w'){|f|f.write(doc)}真可惜,这很简单,我应该自己做的。然后我想检查File类的方法提供了什么ruby​​魔法,或者在调用这些方法时是否有任何“简化”,所以我前往文档here,并检查文件类。1.8.6文档在"fi

  8. Windows Server 2019服务器远程桌面服务部署+深度学习环境配置教程 - 2

    文章目录1.安装WindowsServer20192.开启WLAN服务3.固定IP地址4.开启远程桌面服务4.1添加远程桌面服务4.2激活服务器4.3安装许可证5.配置远程桌面服务5.1配置许可证服务器和授权模式5.2配置连接模式5.3启用计算机的远程功能5.4设置用户能使用简单密码6.配置CUDA环境6.1更新驱动6.2安装CUDA6.3安装cuDNN6.4配置环境变量7.配置Anaconda+Pycharm环境7.1安装Anaconda7.2安装Pycharm8.配置Tensorflow+Pytorch环境8.1创建环境8.2配置pip和conda国内下载源8.3安装Tensorflow-

  9. ruby - 在 Ruby 中实现贝叶斯分类器? - 2

    我想实现一个简单的贝叶斯分类系统来对短信进行基本的情感分析。欢迎提供在Ruby中实现的实用建议。也欢迎提出除贝叶斯之外的其他方法的建议。 最佳答案 IlyaGrigorik在BayesianClassifiers上的这篇博文中对这个问题给出了很好的答案。此外,您不妨看看ai4rrubygem用于贝叶斯分类器的一些替代方法。ID3是一个不错的选择,因为它提供了即使对机器学习技术没有任何真正了解的人也能“理解”的决策树。 关于ruby-在Ruby中实现贝叶斯分类器?,我们在StackOver

  10. 真心推荐8个高质量Java学习网站,一起从入门到精通java语言,大厂java面试真题分享,建议码住!... - 2

    Java自学超全干货分享!学不学自己看着办吧!最近收到了很多知友私信我:”0基础有什么推荐的Java学习工具?”★作为ACM金牌选手,这些年在跟很多学员受教的过程中,积累了一些关于新手Java学习的经验和踩过的坑,今天来跟大家分享几点:1.找准学习路径和方法(选择不对,努力白费)2.合理规划学习时间,不在没必要的技术上浪费时间(找重点)3.找一些志同道合的朋友一起学习(相互鞭策)4.找一个前辈指点(方式方法)“还没开始就结束了”,作为java新手小白,最难自然是找对学习路径和方法……于是,本着一颗无私奉献的心,我连夜整理出了8个优质的Java免费学习网站,分享给大家。NO.1菜鸟教程国内小白入

随机推荐