model 订阅
Model,意思是模特儿,模特儿是英文“model”的音译。模特一般来说要五官端正,身材良好,有气质,展示能力强,另外身高要具备一定的条件。Model在计算机程序设计中有两个概念:一个是三层架构中的实体类,另一个是MVC架构中的模型。 展开全文
Model,意思是模特儿,模特儿是英文“model”的音译。模特一般来说要五官端正,身材良好,有气质,展示能力强,另外身高要具备一定的条件。Model在计算机程序设计中有两个概念:一个是三层架构中的实体类,另一个是MVC架构中的模型。
信息
外文名
model
其他解释
计算机中三层架构中的实体类
中文名
模特儿
解    释
英文“model”的音译
model实体类和模型
Model是计算机程序设计中有两个概念:一个是三层架构中的实体类,另一个是MVC架构中的模型。1、在“三层架构”中,为了面向对象编程,将各层传递的数据封装成实体类,便于数据传递和提高可读性。2、在MVC(模型Model-视图View-控制器Controller)模式中,Model代表模型,是业务流程/状态的处理以及业务规则的制定,接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的核心。
收起全文
精华内容
下载资源
问答
  • ArcGIS之模型构建器(ModelBuilder)视频培训课程,该教程是ArcGIS入门实战课程之后推出的进阶版实战课程。 本课程介绍ArcGIS的模型构建器的应用,分为ArcGIS模型构建器的初识、进阶、应用三个部分。让你的数据处理...
  • add里面只有层layer的内容,当然在序贯式里面,也可以model.add(other_model)加载另外模型,在函数式里面就不太一样,详见函数式。 2、compile 训练模式——solver.prototxt文件 compile ( self , optimizer ...

    不得不说,这深度学习框架更新太快了尤其到了Keras2.0版本,快到Keras中文版好多都是错的,快到官方文档也有旧的没更新,前路坑太多。
    到发文为止,已经有theano/tensorflow/CNTK支持keras,虽然说tensorflow造势很多,但是笔者认为接下来Keras才是正道。
    笔者先学的caffe,从使用来看,比caffe简单超级多,非常好用,特别是重新训练一个模型,但是呢,在fine-tuning的时候,遇到了很多问题,对新手比较棘手。

    中文文档:http://keras-cn.readthedocs.io/en/latest/
    官方文档:https://keras.io/
    文档主要是以keras2.0。


    .

    Keras系列:

    1、keras系列︱Sequential与Model模型、keras基本结构功能(一)
    2、keras系列︱Application中五款已训练模型、VGG16框架(Sequential式、Model式)解读(二)
    3、keras系列︱图像多分类训练与利用bottleneck features进行微调(三)
    4、keras系列︱人脸表情分类与识别:opencv人脸检测+Keras情绪分类(四)
    5、keras系列︱迁移学习:利用InceptionV3进行fine-tuning及预测、完整案例(五)


    零、keras介绍与基本的模型保存

    写成了思维导图,便于观察与理解。

    1.keras网络结构

    这里写图片描述
    ###2.keras网络配置
    这里写图片描述
    其中回调函数callbacks应该是keras的精髓~
    ###3.keras预处理功能
    这里写图片描述

    ###4、模型的节点信息提取

    # 节点信息提取
    config = model.get_config()  # 把model中的信息,solver.prototxt和train.prototxt信息提取出来
    model = Model.from_config(config)  # 还回去
    # or, for Sequential:
    model = Sequential.from_config(config) # 重构一个新的Model模型,用去其他训练,fine-tuning比较好用
    

    ###5、 模型概况查询(包括权重查询)

    # 1、模型概括打印
    model.summary()
    
    # 2、返回代表模型的JSON字符串,仅包含网络结构,不包含权值。可以从JSON字符串中重构原模型:
    from models import model_from_json
    
    json_string = model.to_json()
    model = model_from_json(json_string)
    
    # 3、model.to_yaml:与model.to_json类似,同样可以从产生的YAML字符串中重构模型
    from models import model_from_yaml
    
    yaml_string = model.to_yaml()
    model = model_from_yaml(yaml_string)
    
    # 4、权重获取
    model.get_layer()      #依据层名或下标获得层对象
    model.get_weights()    #返回模型权重张量的列表,类型为numpy array
    model.set_weights()    #从numpy array里将权重载入给模型,要求数组具有与model.get_weights()相同的形状。
    
    # 查看model中Layer的信息
    model.layers 查看layer信息
    
    

    ###6、模型保存与加载

    model.save_weights(filepath)
    # 将模型权重保存到指定路径,文件类型是HDF5(后缀是.h5)
    
    model.load_weights(filepath, by_name=False)
    # 从HDF5文件中加载权重到当前模型中, 默认情况下模型的结构将保持不变。
    # 如果想将权重载入不同的模型(有些层相同)中,则设置by_name=True,只有名字匹配的层才会载入权重
    

    .

    7、如何在keras中设定GPU使用的大小

    本节来源于:深度学习theano/tensorflow多显卡多人使用问题集(参见:Limit the resource usage for tensorflow backend · Issue #1538 · fchollet/keras · GitHub
    在使用keras时候会出现总是占满GPU显存的情况,可以通过重设backend的GPU占用情况来进行调节。

    import tensorflow as tf
    from keras.backend.tensorflow_backend import set_session
    config = tf.ConfigProto()
    config.gpu_options.per_process_gpu_memory_fraction = 0.3
    set_session(tf.Session(config=config))
    

    需要注意的是,虽然代码或配置层面设置了对显存占用百分比阈值,但在实际运行中如果达到了这个阈值,程序有需要的话还是会突破这个阈值。换而言之如果跑在一个大数据集上还是会用到更多的显存。以上的显存限制仅仅为了在跑小数据集时避免对显存的浪费而已。(2017年2月20日补充)

    8.更科学地模型训练与模型保存

    filepath = 'model-ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5'
    checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')
    # fit model
    model.fit(x, y, epochs=20, verbose=2, callbacks=[checkpoint], validation_data=(x, y))
    

    save_best_only打开之后,会如下:

     ETA: 3s - loss: 0.5820Epoch 00017: val_loss did not improve
    

    如果val_loss 提高了就会保存,没有提高就不会保存。

    9.如何在keras中使用tensorboard

        RUN = RUN + 1 if 'RUN' in locals() else 1   # locals() 函数会以字典类型返回当前位置的全部局部变量。
    
        LOG_DIR = model_save_path + '/training_logs/run{}'.format(RUN)
        LOG_FILE_PATH = LOG_DIR + '/checkpoint-{epoch:02d}-{val_loss:.4f}.hdf5'   # 模型Log文件以及.h5模型文件存放地址
    
        tensorboard = TensorBoard(log_dir=LOG_DIR, write_images=True)
        checkpoint = ModelCheckpoint(filepath=LOG_FILE_PATH, monitor='val_loss', verbose=1, save_best_only=True)
        early_stopping = EarlyStopping(monitor='val_loss', patience=5, verbose=1)
    
        history = model.fit_generator(generator=gen.generate(True), steps_per_epoch=int(gen.train_batches / 4),
                                      validation_data=gen.generate(False), validation_steps=int(gen.val_batches / 4),
                                      epochs=EPOCHS, verbose=1, callbacks=[tensorboard, checkpoint, early_stopping])
    

    都是在回调函数中起作用:

    • EarlyStopping patience:当early
      (1)stop被激活(如发现loss相比上一个epoch训练没有下降),则经过patience个epoch后停止训练。
      (2)mode:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值停止下降则中止训练。在max模式下,当检测值不再上升则停止训练。

    • 模型检查点ModelCheckpoint
      (1)save_best_only:当设置为True时,将只保存在验证集上性能最好的模型
      (2) mode:‘auto’,‘min’,‘max’之一,在save_best_only=True时决定性能最佳模型的评判准则,例如,当监测值为val_acc时,模式应为max,当检测值为val_loss时,模式应为min。在auto模式下,评价准则由被监测值的名字自动推断。
      (3)save_weights_only:若设置为True,则只保存模型权重,否则将保存整个模型(包括模型结构,配置信息等)
      (4)period:CheckPoint之间的间隔的epoch数

    • 可视化tensorboard write_images: 是否将模型权重以图片的形式可视化

    其他内容可参考keras中文文档

    .


    一、Sequential 序贯模型

    序贯模型是函数式模型的简略版,为最简单的线性、从头到尾的结构顺序,不分叉。

    Sequential模型的基本组件

    一般需要:

    • 1、model.add,添加层;
    • 2、model.compile,模型训练的BP模式设置;
    • 3、model.fit,模型训练参数设置 + 训练;
    • 4、模型评估
    • 5、模型预测

    1. add:添加层——train_val.prototxt

    add(self, layer)
    
    # 譬如:
    model.add(Dense(32, activation='relu', input_dim=100))
    model.add(Dropout(0.25))
    

    add里面只有层layer的内容,当然在序贯式里面,也可以model.add(other_model)加载另外模型,在函数式里面就不太一样,详见函数式。

    2、compile 训练模式——solver.prototxt文件

    compile(self, optimizer, loss, metrics=None, sample_weight_mode=None)
    

    其中:
    optimizer: 字符串(预定义优化器名)或优化器对象,参考优化器
    loss: 字符串(预定义损失函数名)或目标函数,参考损失函数
    metrics: 列表,包含评估模型在训练和测试时的网络性能的指标,典型用法是metrics=[‘accuracy’]
    sample_weight_mode:如果你需要按时间步为样本赋权(2D权矩阵),将该值设为“temporal”。
    默认为“None”,代表按样本赋权(1D权)。在下面fit函数的解释中有相关的参考内容。
    kwargs: 使用TensorFlow作为后端请忽略该参数,若使用Theano作为后端,kwargs的值将会传递给 K.function

    注意:
    模型在使用前必须编译,否则在调用fit或evaluate时会抛出异常。

    3、fit 模型训练参数+训练——train.sh+soler.prototxt(部分)

    fit(self, x, y, batch_size=32, epochs=10, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)
    

    本函数将模型训练nb_epoch轮,其参数有:

    • x:输入数据。如果模型只有一个输入,那么x的类型是numpy
      array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array
    • y:标签,numpy array
    • batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
    • epochs:整数,训练的轮数,每个epoch会把训练集轮一遍。
    • verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
    • callbacks:list,其中的元素是keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数
    • validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。
    • validation_data:形式为(X,y)的tuple,是指定的验证集。此参数将覆盖validation_spilt。
    • shuffle:布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱。
    • class_weight:字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)
    • sample_weight:权值的numpy
      array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode=‘temporal’。
    • initial_epoch: 从该参数指定的epoch开始训练,在继续之前的训练时有用。

    fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况
    注意:
    要与之后的fit_generator做区别,两者输入x/y不同。

    4.evaluate 模型评估

    evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
    

    本函数按batch计算在某些输入数据上模型的误差,其参数有:

    • x:输入数据,与fit一样,是numpy array或numpy array的list
    • y:标签,numpy array
    • batch_size:整数,含义同fit的同名参数
    • verbose:含义同fit的同名参数,但只能取0或1
    • sample_weight:numpy array,含义同fit的同名参数

    本函数返回一个测试误差的标量值(如果模型没有其他评价指标),或一个标量的list(如果模型还有其他的评价指标)。model.metrics_names将给出list中各个值的含义。

    如果没有特殊说明,以下函数的参数均保持与fit的同名参数相同的含义
    如果没有特殊说明,以下函数的verbose参数(如果有)均只能取0或1

    5 predict 模型评估

    predict(self, x, batch_size=32, verbose=0)
    predict_classes(self, x, batch_size=32, verbose=1)
    predict_proba(self, x, batch_size=32, verbose=1)
    

    本函数按batch获得输入数据对应的输出,其参数有:

    函数的返回值是预测值的numpy array
    predict_classes:本函数按batch产生输入数据的类别预测结果;
    predict_proba:本函数按batch产生输入数据属于各个类别的概率

    6 on_batch 、batch的结果,检查

    train_on_batch(self, x, y, class_weight=None, sample_weight=None)
    test_on_batch(self, x, y, sample_weight=None)
    predict_on_batch(self, x)
    
    • train_on_batch:本函数在一个batch的数据上进行一次参数更新,函数返回训练误差的标量值或标量值的list,与evaluate的情形相同。
    • test_on_batch:本函数在一个batch的样本上对模型进行评估,函数的返回与evaluate的情形相同
    • predict_on_batch:本函数在一个batch的样本上对模型进行测试,函数返回模型在一个batch上的预测结果

    7 fit_generator

    #利用Python的生成器,逐个生成数据的batch并进行训练。
    #生成器与模型将并行执行以提高效率。
    #例如,该函数允许我们在CPU上进行实时的数据提升,同时在GPU上进行模型训练
    # 参考链接:http://keras-cn.readthedocs.io/en/latest/models/sequential/
    

    有了该函数,图像分类训练任务变得很简单。

    fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_q_size=10, workers=1, pickle_safe=False, initial_epoch=0)
    
    # 案例:
    def generate_arrays_from_file(path):
        while 1:
                f = open(path)
                for line in f:
                    # create Numpy arrays of input data
                    # and labels, from each line in the file
                    x, y = process_line(line)
                    yield (x, y)
            f.close()
    
    model.fit_generator(generate_arrays_from_file('/my_file.txt'),
            samples_per_epoch=10000, epochs=10)
    

    其他的两个辅助的内容:

    evaluate_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False)
    predict_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False, verbose=0)
    

    evaluate_generator:本函数使用一个生成器作为数据源评估模型,生成器应返回与test_on_batch的输入数据相同类型的数据。该函数的参数与fit_generator同名参数含义相同,steps是生成器要返回数据的轮数。
    predcit_generator:本函数使用一个生成器作为数据源预测模型,生成器应返回与test_on_batch的输入数据相同类型的数据。该函数的参数与fit_generator同名参数含义相同,steps是生成器要返回数据的轮数。

    案例一:简单的2分类

    For a single-input model with 2 classes (binary classification):

    from keras.models import Sequential
    from keras.layers import Dense, Activation
    
    #模型搭建阶段
    model= Sequential()
    model.add(Dense(32, activation='relu', input_dim=100))
    # Dense(32) is a fully-connected layer with 32 hidden units.
    model.add(Dense(1, activation='sigmoid'))
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    

    其中:
    Sequential()代表类的初始化;
    Dense代表全连接层,此时有32个神经元,最后接relu,输入的是100维度
    model.add,添加新的全连接层,
    compile,跟prototxt一样,一些训练参数,solver.prototxt

    # Generate dummy data
    import numpy as np
    data = np.random.random((1000, 100))
    labels = np.random.randint(2, size=(1000, 1))
    
    # Train the model, iterating on the data in batches of 32 samples
    model.fit(data, labels, nb_epoch =10, batch_size=32)
    

    之前报过这样的错误,是因为版本的问题。 版本1.2里面是nb_epoch ,而keras2.0是epochs = 10

     error:
        TypeError: Received unknown keyword arguments: {'epochs': 10}
    

    其中:
    epoch=batch_size * iteration,10次epoch代表训练十次训练集

    案例二:多分类-VGG的卷积神经网络

    import numpy as np
    import keras
    from keras.models import Sequential
    from keras.layers import Dense, Dropout, Flatten
    from keras.layers import Conv2D, MaxPooling2D
    from keras.optimizers import SGD
    from keras.utils import np_utils
    
    # Generate dummy data
    x_train = np.random.random((100, 100, 100, 3))
    # 100张图片,每张100*100*3
    y_train = keras.utils.to_categorical(np.random.randint(10, size=(100, 1)), num_classes=10)
    # 100*10
    x_test = np.random.random((20, 100, 100, 3))
    y_test = keras.utils.to_categorical(np.random.randint(10, size=(20, 1)), num_classes=10)
    # 20*100
    
    model = Sequential()
    # input: 100x100 images with 3 channels -> (100, 100, 3) tensors.
    # this applies 32 convolution filters of size 3x3 each.
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(10, activation='softmax'))
    
    sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='categorical_crossentropy', optimizer=sgd)
    
    model.fit(x_train, y_train, batch_size=32, epochs=10)
    score = model.evaluate(x_test, y_test, batch_size=32)
    

    标准序贯网络,标签的训练模式
    注意:
    这里非常重要的一点,对于我这样的新手,这一步的作用?

    keras.utils.to_categorical
    

    特别是多分类时候,我之前以为输入的就是一列(100,),但是keras在多分类任务中是不认得这个的,所以需要再加上这一步,让其转化为Keras认得的数据格式。

    案例三:使用LSTM的序列分类

    from keras.models import Sequential
    from keras.layers import Dense, Dropout
    from keras.layers import Embedding
    from keras.layers import LSTM
    
    model = Sequential()
    model.add(Embedding(max_, output_dim=256))
    model.add(LSTM(128))
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))
    
    model.compile(loss='binary_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    
    model.fit(x_train, y_train, batch_size=16, epochs=10)
    score = model.evaluate(x_test, y_test, batch_size=16)
    

    .


    三、Model式模型

    来自keras中文文档:http://keras-cn.readthedocs.io/en/latest/
    比序贯模型要复杂,但是效果很好,可以同时/分阶段输入变量,分阶段输出想要的模型;
    一句话,只要你的模型不是类似VGG一样一条路走到黑的模型,或者你的模型需要多于一个的输出,那么你总应该选择函数式模型。

    不同之处:
    书写结构完全不一致

    函数式模型基本属性与训练流程

    一般需要:
    1、model.layers,添加层信息;
    2、model.compile,模型训练的BP模式设置;
    3、model.fit,模型训练参数设置 + 训练;
    4、evaluate,模型评估;
    5、predict 模型预测

    1 常用Model属性

    model.layers:组成模型图的各个层
    model.inputs:模型的输入张量列表
    model.outputs:模型的输出张量列表
    

    2 compile 训练模式设置——solver.prototxt

    compile(self, optimizer, loss, metrics=None, loss_weights=None, sample_weight_mode=None)
    

    本函数编译模型以供训练,参数有

    optimizer:优化器,为预定义优化器名或优化器对象,参考优化器
    loss:损失函数,为预定义损失函数名或一个目标函数,参考损失函数
    metrics:列表,包含评估模型在训练和测试时的性能的指标,典型用法是metrics=[‘accuracy’]如果要在多输出模型中为不同的输出指定不同的指标,可像该参数传递一个字典,例如metrics={‘ouput_a’: ‘accuracy’}
    sample_weight_mode:如果你需要按时间步为样本赋权(2D权矩阵),将该值设为“temporal”。默认为“None”,代表按样本赋权(1D权)。
    如果模型有多个输出,可以向该参数传入指定sample_weight_mode的字典或列表。在下面fit函数的解释中有相关的参考内容。

    【Tips】如果你只是载入模型并利用其predict,可以不用进行compile。在Keras中,compile主要完成损失函数和优化器的一些配置,是为训练服务的。predict会在内部进行符号函数的编译工作(通过调用_make_predict_function生成函数)

    3 fit 模型训练参数设置 + 训练

    fit(self, x=None, y=None, batch_size=32, epochs=1, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)
    

    本函数用以训练模型,参数有:

    • x:输入数据。如果模型只有一个输入,那么x的类型是numpy
      array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy
      array。如果模型的每个输入都有名字,则可以传入一个字典,将输入名与其输入数据对应起来。
    • y:标签,numpy array。如果模型有多个输出,可以传入一个numpy
      array的list。如果模型的输出拥有名字,则可以传入一个字典,将输出名与其标签对应起来。
    • batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
    • nb_epoch:整数,训练的轮数,训练数据将会被遍历nb_epoch次。Keras中nb开头的变量均为"number of"的意思
    • verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
    • callbacks:list,其中的元素是keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数
    • validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之后,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。
    • validation_data:形式为(X,y)或(X,y,sample_weights)的tuple,是指定的验证集。此参数将覆盖validation_spilt。
    • shuffle:布尔值,表示是否在训练过程中每个epoch前随机打乱输入样本的顺序。
    • class_weight:字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)。该参数在处理非平衡的训练数据(某些类的训练样本数很少)时,可以使得损失函数对样本数不足的数据更加关注。
    • sample_weight:权值的numpy
      array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode=‘temporal’。
    • initial_epoch: 从该参数指定的epoch开始训练,在继续之前的训练时有用。

    输入数据与规定数据不匹配时会抛出错误

    fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况

    4.evaluate,模型评估

    evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
    

    本函数按batch计算在某些输入数据上模型的误差,其参数有:

    • x:输入数据,与fit一样,是numpy array或numpy array的list
    • y:标签,numpy array
    • batch_size:整数,含义同fit的同名参数
    • verbose:含义同fit的同名参数,但只能取0或1
    • sample_weight:numpy array,含义同fit的同名参数

    本函数返回一个测试误差的标量值(如果模型没有其他评价指标),或一个标量的list(如果模型还有其他的评价指标)。model.metrics_names将给出list中各个值的含义。

    如果没有特殊说明,以下函数的参数均保持与fit的同名参数相同的含义
    如果没有特殊说明,以下函数的verbose参数(如果有)均只能取0或1

    5.predict 模型预测

    predict(self, x, batch_size=32, verbose=0)
    
    

    本函数按batch获得输入数据对应的输出,其参数有:

    函数的返回值是预测值的numpy array

    模型检查 on_batch

    train_on_batch(self, x, y, class_weight=None, sample_weight=None)
    test_on_batch(self, x, y, sample_weight=None)
    predict_on_batch(self, x)
    

    train_on_batch:本函数在一个batch的数据上进行一次参数更新,函数返回训练误差的标量值或标量值的list,与evaluate的情形相同。
    test_on_batch:本函数在一个batch的样本上对模型进行评估,函数的返回与evaluate的情形相同;
    predict_on_batch:本函数在一个batch的样本上对模型进行测试,函数返回模型在一个batch上的预测结果

    _generator

    fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_q_size=10, workers=1, pickle_safe=False, initial_epoch=0)
    evaluate_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False)
    

    案例一:简单的单层-全连接网络

    from keras.layers import Input, Dense
    from keras.models import Model
    
    # This returns a tensor
    inputs = Input(shape=(784,))
    
    # a layer instance is callable on a tensor, and returns a tensor
    x = Dense(64, activation='relu')(inputs)
    # 输入inputs,输出x
    # (inputs)代表输入
    x = Dense(64, activation='relu')(x)
    # 输入x,输出x
    predictions = Dense(10, activation='softmax')(x)
    # 输入x,输出分类
    
    # This creates a model that includes
    # the Input layer and three Dense layers
    model = Model(inputs=inputs, outputs=predictions)
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    model.fit(data, labels)  # starts training
    

    其中:
    可以看到结构与序贯模型完全不一样,其中x = Dense(64, activation=‘relu’)(inputs)中:(input)代表输入;x代表输出
    model = Model(inputs=inputs, outputs=predictions);该句是函数式模型的经典,可以同时输入两个input,然后输出output两个模型

    案例二:视频处理

    x = Input(shape=(784,))
    # This works, and returns the 10-way softmax we defined above.
    y = model(x)
    # model里面存着权重,然后输入x,输出结果,用来作fine-tuning
    
    # 分类->视频、实时处理
    from keras.layers import TimeDistributed
    
    # Input tensor for sequences of 20 timesteps,
    # each containing a 784-dimensional vector
    input_sequences = Input(shape=(20, 784))
    # 20个时间间隔,输入784维度的数据
    
    # This applies our previous model to every timestep in the input sequences.
    # the output of the previous model was a 10-way softmax,
    # so the output of the layer below will be a sequence of 20 vectors of size 10.
    processed_sequences = TimeDistributed(model)(input_sequences)
    # Model是已经训练好的
    

    其中:
    Model是已经训练好的,现在用来做迁移学习;
    其中还可以通过TimeDistributed来进行实时预测;
    TimeDistributed(model)(input_sequences),input_sequences代表序列输入;model代表已训练的模型

    案例三:双输入、双模型输出:LSTM 时序预测

    本案例很好,可以了解到Model的精髓在于他的任意性,给编译者很多的便利。

    输入:
    新闻语料;新闻语料对应的时间
    输出:
    新闻语料的预测模型;新闻语料+对应时间的预测模型
    这里写图片描述

    模型一:只针对新闻语料的LSTM模型

    from keras.layers import Input, Embedding, LSTM, Dense
    from keras.models import Model
    
    # Headline input: meant to receive sequences of 100 integers, between 1 and 10000.
    # Note that we can name any layer by passing it a "name" argument.
    main_input = Input(shape=(100,), dtype='int32', name='main_input')
    # 一个100词的BOW序列
    
    # This embedding layer will encode the input sequence
    # into a sequence of dense 512-dimensional vectors.
    x = Embedding(output_dim=512, input_dim=10000, input_length=100)(main_input)
    # Embedding层,把100维度再encode成512的句向量,10000指的是词典单词总数
    
    
    # A LSTM will transform the vector sequence into a single vector,
    # containing information about the entire sequence
    lstm_out = LSTM(32)(x)
    # ? 32什么意思?????????????????????
    
    #然后,我们插入一个额外的损失,使得即使在主损失很高的情况下,LSTM和Embedding层也可以平滑的训练。
    
    auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(lstm_out)
    #再然后,我们将LSTM与额外的输入数据串联起来组成输入,送入模型中:
    # 模型一:只针对以上的序列做的预测模型
    

    组合模型:新闻语料+时序

    # 模型二:组合模型
    auxiliary_input = Input(shape=(5,), name='aux_input')  # 新加入的一个Input,5维度
    x = keras.layers.concatenate([lstm_out, auxiliary_input])   # 组合起来,对应起来
    
    
    # We stack a deep densely-connected network on top
    # 组合模型的形式
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    # And finally we add the main logistic regression layer
    main_output = Dense(1, activation='sigmoid', name='main_output')(x)
    
    
    #最后,我们定义整个2输入,2输出的模型:
    model = Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])
    #模型定义完毕,下一步编译模型。
    #我们给额外的损失赋0.2的权重。我们可以通过关键字参数loss_weights或loss来为不同的输出设置不同的损失函数或权值。
    #这两个参数均可为Python的列表或字典。这里我们给loss传递单个损失函数,这个损失函数会被应用于所有输出上。
    
    

    其中:Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])是核心,
    Input两个内容,outputs两个模型

    # 训练方式一:两个模型一个loss
    model.compile(optimizer='rmsprop', loss='binary_crossentropy',
                  loss_weights=[1., 0.2])
    #编译完成后,我们通过传递训练数据和目标值训练该模型:
    
    model.fit([headline_data, additional_data], [labels, labels],
              epochs=50, batch_size=32)
    
    # 训练方式二:两个模型,两个Loss
    #因为我们输入和输出是被命名过的(在定义时传递了“name”参数),我们也可以用下面的方式编译和训练模型:
    model.compile(optimizer='rmsprop',
                  loss={'main_output': 'binary_crossentropy', 'aux_output': 'binary_crossentropy'},
                  loss_weights={'main_output': 1., 'aux_output': 0.2})
    
    # And trained it via:
    model.fit({'main_input': headline_data, 'aux_input': additional_data},
              {'main_output': labels, 'aux_output': labels},
              epochs=50, batch_size=32)
    
    

    因为输入两个,输出两个模型,所以可以分为设置不同的模型训练参数

    案例四:共享层:对应关系、相似性

    一个节点,分成两个分支出去

    import keras
    from keras.layers import Input, LSTM, Dense
    from keras.models import Model
    
    tweet_a = Input(shape=(140, 256))
    tweet_b = Input(shape=(140, 256))
    #若要对不同的输入共享同一层,就初始化该层一次,然后多次调用它
    # 140个单词,每个单词256维度,词向量
    # 
    
    # This layer can take as input a matrix
    # and will return a vector of size 64
    shared_lstm = LSTM(64)
    # 返回一个64规模的向量
    
    # When we reuse the same layer instance
    # multiple times, the weights of the layer
    # are also being reused
    # (it is effectively *the same* layer)
    encoded_a = shared_lstm(tweet_a)
    encoded_b = shared_lstm(tweet_b)
    
    # We can then concatenate the two vectors:
        # 连接两个结果
        # axis=-1?????
    merged_vector = keras.layers.concatenate([encoded_a, encoded_b], axis=-1)
    
    # And add a logistic regression on top
    predictions = Dense(1, activation='sigmoid')(merged_vector)
    # 其中的1 代表什么????
    
    # We define a trainable model linking the
    # tweet inputs to the predictions
    model = Model(inputs=[tweet_a, tweet_b], outputs=predictions)
    
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    model.fit([data_a, data_b], labels, epochs=10)
    # 训练模型,然后预测
    

    案例五:抽取层节点内容

    # 1、单节点
    a = Input(shape=(140, 256))
    lstm = LSTM(32)
    encoded_a = lstm(a)
    assert lstm.output == encoded_a
    # 抽取获得encoded_a的输出张量
    
    # 2、多节点
    a = Input(shape=(140, 256))
    b = Input(shape=(140, 256))
    
    lstm = LSTM(32)
    encoded_a = lstm(a)
    encoded_b = lstm(b)
    
    assert lstm.get_output_at(0) == encoded_a
    assert lstm.get_output_at(1) == encoded_b
    
    # 3、图像层节点
    # 对于input_shape和output_shape也是一样,如果一个层只有一个节点,
    #或所有的节点都有相同的输入或输出shape,
    #那么input_shape和output_shape都是没有歧义的,并也只返回一个值。
    #但是,例如你把一个相同的Conv2D应用于一个大小为(3,32,32)的数据,
    #然后又将其应用于一个(3,64,64)的数据,那么此时该层就具有了多个输入和输出的shape,
    #你就需要显式的指定节点的下标,来表明你想取的是哪个了
    a = Input(shape=(3, 32, 32))
    b = Input(shape=(3, 64, 64))
    
    conv = Conv2D(16, (3, 3), padding='same')
    conved_a = conv(a)
    
    # Only one input so far, the following will work:
    assert conv.input_shape == (None, 3, 32, 32)
    
    conved_b = conv(b)
    # now the `.input_shape` property wouldn't work, but this does:
    assert conv.get_input_shape_at(0) == (None, 3, 32, 32)
    assert conv.get_input_shape_at(1) == (None, 3, 64, 64)
    

    案例六:视觉问答模型

    #这个模型将自然语言的问题和图片分别映射为特征向量,
    #将二者合并后训练一个logistic回归层,从一系列可能的回答中挑选一个。
    from keras.layers import Conv2D, MaxPooling2D, Flatten
    from keras.layers import Input, LSTM, Embedding, Dense
    from keras.models import Model, Sequential
    
    # First, let's define a vision model using a Sequential model.
    # This model will encode an image into a vector.
    vision_model = Sequential()
    vision_model.add(Conv2D(64, (3, 3) activation='relu', padding='same', input_shape=(3, 224, 224)))
    vision_model.add(Conv2D(64, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
    vision_model.add(Conv2D(128, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
    vision_model.add(Conv2D(256, (3, 3), activation='relu'))
    vision_model.add(Conv2D(256, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Flatten())
    
    # Now let's get a tensor with the output of our vision model:
    image_input = Input(shape=(3, 224, 224))
    encoded_image = vision_model(image_input)
    
    # Next, let's define a language model to encode the question into a vector.
    # Each question will be at most 100 word long,
    # and we will index words as integers from 1 to 9999.
    question_input = Input(shape=(100,), dtype='int32')
    embedded_question = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input)
    encoded_question = LSTM(256)(embedded_question)
    
    # Let's concatenate the question vector and the image vector:
    merged = keras.layers.concatenate([encoded_question, encoded_image])
    
    # And let's train a logistic regression over 1000 words on top:
    output = Dense(1000, activation='softmax')(merged)
    
    # This is our final model:
    vqa_model = Model(inputs=[image_input, question_input], outputs=output)
    
    # The next stage would be training this model on actual data.
    

    .

    延伸一:fine-tuning时如何加载No_top的权重

    如果你需要加载权重到不同的网络结构(有些层一样)中,例如fine-tune或transfer-learning,你可以通过层名字来加载模型:
    model.load_weights(‘my_model_weights.h5’, by_name=True)
    例如:

    假如原模型为:

        model = Sequential()
        model.add(Dense(2, input_dim=3, name="dense_1"))
        model.add(Dense(3, name="dense_2"))
        ...
        model.save_weights(fname)
    
    # new model
    model = Sequential()
    model.add(Dense(2, input_dim=3, name="dense_1"))  # will be loaded
    model.add(Dense(10, name="new_dense"))  # will not be loaded
    
    # load weights from first model; will only affect the first layer, dense_1.
    model.load_weights(fname, by_name=True)
    

    延伸二:应对不均衡样本的情况

    使用:class_weight,sample_weight

    两者的区别为:

    • class_weight—主要针对的上数据不均衡问题,比如:异常检测的二项分类问题,异常数据仅占1%,正常数据占99%; 此时就要设置不同类对loss的影响。

    • sample_weight—主要解决的是样本质量不同的问题,比如前1000个样本的可信度,那么它的权重就要高,后1000个样本可能有错、不可信,那么权重就要调低。

    class_weight的使用:

    cw = {0: 1, 1: 50}
    model.fit(x_train, y_train,batch_size=batch_size,epochs=epochs,verbose=1,callbacks=cbks,validation_data=(x_test, y_test), shuffle=True,class_weight=cw)
    

    sample_weight的使用:
    来源:https://www.kaggle.com/c/jigsaw-toxic-comment-classification-challenge/discussion/46673

    from sklearn.utils import class_weight
    
    list_classes = ["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"]
    y = train[list_classes].values
    sample_weights = class_weight.compute_sample_weight('balanced', y)
    
    model.fit(X_t, y, batch_size=batch_size, epochs=epochs,validation_split=0.1,sample_weight=sample_weights, callbacks=callbacks_list)
    
    展开全文
  • Qt中model/view设计模式

    千次阅读 2018-12-13 17:03:55
    Qt Model/View 学习笔记 (一)   Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系。这种结构带来的 功能上的分离给了开发人员更大的弹性来定制数据项的表示,它也提供一个标准的...

    Qt Model/View 学习笔记 (一)

     

    Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系。这种结构带来的

    功能上的分离给了开发人员更大的弹性来定制数据项的表示,它也提供一个标准的model接口,使得更多的

    数据源可以被这些item view使用。这里对model/view的结构进行了描述,结构中的每个组件都进行了解释,

    给出了一些例子说明了提供的这些类如何使用。

    Model/View  结构

    Model-View-Controller(MVC), 是从Smalltalk发展而来的一种设计模式,常被用于构建用户界面。经典设计模式的著作中有这样的描述:

    MVC 由三种对象组成。Model是应用程序对象,View是它的屏幕表示,Controller定义了用户界面如何对用户输入进行响应。在MVC之前,用户界面设计倾向于三者揉合在一起,MVC对它们进行了解耦,提高了灵活性与重用性。

    假如把view与controller结合在一起,结果就是model/view结构。这个结构依然是把数据存储与数据表示进行了分离,它与MVC都基于同样的思想,但它更简单一些。这种分离使得在几个不同的view上显示同一个数据成为可能,也可以重新实现新的view,而不必改变底层的数据结构。为了更灵活的对用户输入进行处理,引入了delegate这个概念。它的好处是,数据项的渲染与编程可以进行定制。

    QTreeView - zhengjiu_520 - !snows snowy world!

    如上图所示,model与数据源通讯,并提供接口给结构中的别的组件使用。通讯的性质依赖于数据源的种类

    与model实现的方式。view从model获取model indexes,后者是数据项的引用。通过把model indexes提供给model,view可以从数据源中获取数据。

    在标准的views中,delegate会对数据项进行渲染,当某个数据项被选中时,delegate通过model indexes与model直接进行交流。总的来说,model/view 相关类可以被分成上面所提到的三组:models,views,delegates。这些组件通过抽象类来定义,它们提供了共同的接口,在某些情况下,还提供了缺省的实现。抽象类意味着需要子类化以提供完整的其他组件希望的功能。这也允许实现定制的组件。models,views,delegates之间通过信号,槽机制来进行通讯:

    从model发出的信号通知view数据源中的数据发生了改变。

    从view发出的信号提供了有关被显示的数据项与用户交互的信息。

    从delegate发生的信号被用于在编辑时通知model和view关于当前编辑器的状态信息。

    Models

    所有的item models都基于QAbstractItemModel类,这个类定义了用于views和delegates访问数据的接口。

    数据本身不必存储在model,数据可被置于一个数据结构或另外的类,文件,数据库,或别的程序组件中。

    关于model的基本概念在Model Classes部分中描述。

    QAbstractItemModel提供给数据一个接口,它非常灵活,基本满足views的需要,无论数据用以下任何样的形式

    表现,如tables,lists,trees。然而,当你重新实现一个model时,如果它基于table或list形式的数据结构,最好从QAbstractListModel,QAbstractTableModel开始做起,因为它们提供了适当的常规功能的缺省实现。这些类可以被子类化以支持特殊的定制需求。子类化model的过程在Create New Model部分讨论

    QT提供了一些现成的models用于处理数据项:

    QStringListModel 用于存储简单的QString列表。

    QStandardItemModel 管理复杂的树型结构数据项,每项都可以包含任意数据。

    QDirModel  提供本地文件系统中的文件与目录信息。

    QSqlQueryModel, QSqlTableModel,QSqlRelationTableModel用来访问数据库。

    假如这些标准Model不满足你的需要,你应该子类化QAbstractItemModel,QAbstractListModel或是

    QAbstractTableModel来定制。

    Views

    不同的view都完整实现了各自的功能:QListView把数据显示为一个列表,QTableView把Model 中的数据以table的形式表现,QTreeView 用具有层次结构的列表来显示model中的数据。这些类都基于QAbstractItemView抽象基类,尽管这些类都是现成的,完整的进行了实现,但它们都可以用于子类化以便满足定制需求。

    Delegates

    QAbstractItemDelegate 是model/view架构中的用于delegate的抽象基类。缺省的delegate实现在QItemDelegate类中提供。它可以用于Qt标准views的缺省 delegate.

    排序

    在model/view架构中,有两种方法进行排序,选择哪种方法依赖于你的底层Model。

    假如你的model是可排序的,也就是它重新实现了QAbstractItemModel::sort()函数,QTableView与QTreeView都提供了API,允许你以编程的方式对Model数据进行排序。另外,你也可以进行交互方式下的排序(例如,允许用户通过点击view表头的方式对数据进行排序),可以这样做:把QHeaderView::sectionClicked()信号与QTableView::sortByColum()槽或QTreeView::sortByColumn()槽进行联结就好了。

    另一种方法是,假如你的model没有提供需要的接口或是你想用list view表示数据,可以用一个代理

    model在用view表示数据之前对你的model数据结构进行转换。

    便利类

    许多便利类都源于标准的view类,它们方便了那些使用Qt中基于项的view与table类,它们不应该被子类化,

    它们只是为Qt 3的等价类提供一个熟悉的接口。这些类有QListWidget,QTreeWidget,QTableWidget,它们提供了如Qt 3中的QListBox, QlistView,QTable相似的行为。这些类比View类缺少灵活性,不能用于任意的models,推介使用model/view的方法处理数据。

     

    Qt Model/View 学习笔记 (二) 
    介绍
    Qt提供了两个标准的models:QStandardItemModel和QDirModel。QStandardItemModel是一个多用途的
    model,可用于表示list,table,tree views所需要的各种不同的数据结构。这个model也持有数据。QDirModel
    维护相关的目录内容的信息,它本身不持有数据,仅是对本地文件系统中的文件与目录的描述。
    QDirModel是一个现成的model,很容易进行配置以用于现存的数据,使用这个model,可以很好地展示如何
    给一个现成的view设定model,研究如何用model indexes来操纵数据。

    model与views的搭配使用

    QListView与QTreeView很适合与QDirModel搭配。下面的例子在tree view与list view显示了相同的信息,QDirModel提供了目录内容数据。这两个Views共享用户选择,因此每个被选择的项在每个view中都会被高亮。

    QTreeView - zhengjiu_520 - !snows snowy world!先装配出一个QDirModel以供使用,再创建views去显示目录的内容。这给我展示了使用model的最简单的方式。
    model的创建与使用都在main()函数中完成:
     int main(int argc, char *argv[])
     {
         QApplication app(argc, argv);
         QSplitter *splitter = new QSplitter;

         QDirModel *model = new QDirModel;
        //从缺省目录创建数据
         QTreeView *tree = new QTreeView(splitter);
         tree->setModel(model);
         tree->setRootIndex(model->index(QDir::currentPath()));

         QListView *list = new QListView(splitter);
         list->setModel(model);
         list->setRootIndex(model->index(QDir::currentPath()));
         //配置一个view去显示model中的数据,只需要简单地调用setModel(),并把目录model作为参数传递
         //setRootIndex()告诉views显示哪个目录的信息,这需要提供一个model index,然后用这个
         //model index去model中去获取数据
         //index()这个函数是QDirModel特有的,通过把一个目录做为参数,得到了需要的model index
         //其他的代码只是窗口show出来,进入程序的事件循环就好了
          splitter->setWindowTitle("Two views onto the same directory model");
         splitter->show();
         return app.exec();
     }


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kailan818/archive/2009/11/25/4868904.aspx

    Qt Model/View 学习笔记 (三)

    清源游民 gameogre@gmail.com

    Model类

    基本概念

    在model/view构架中,model为view和delegates使用数据提供了标准接口。在Qt中,标准接口QAbstractItemModel类中被定义。不管数据在底层以何种数据结构存储,QAabstractItemModel的子类会以层次结构的形式来表示数据,结构中包含了数据项表。我们按这种约定来访问model中的数据项,但这个约定不会对如何显示这些数据有任何限制。数据发生改变时,model通过信号槽机制来通知关联的views。

    QTreeView - zhengjiu_520 - !snows snowy world!

    Model Indexes

    为了使数据存储与数据访问分开,引入了model index的概念。通过model index,可以引用model中的数据项,Views和delegates都使用indexes来访问数据项,然后再显示出来。因此,只有model需要了解如何获取数据,被model管理的数据类型可以非常广泛地被定义。Model indexes包含一个指向创建它们的model的指针,这会在配合多个model工作时避免混乱。

    QAbstractItemModel *model = index.model();

    model indexes提供了对一项数据信息的临时引用,通过它可以访问或是修改model中的数据。既然model有时会重新组织内部的数据结构,这时model indexes便会失效,因此不应该保存临时的model indexes。假如需要一个对数据信息的长期的引用,那么应该创建一个persistent model index。这个引用会保持更新。临时的model indexes由QModelIndex提供,而具有持久能力的model indexes则由QPersistentModelIndex提供。在获取对应一个数据项的model index时,需要考虑有关于model的三个属性:行数,列数,父项的model index。

    行与列

    在最基本的形式中,一个model可作为一个简单的表来访问,每个数据项由行,列数来定位。这必不意味着

    底层的数据用数组结构来存储。行和列的使用仅仅是一种约定,它允许组件之间相互通讯。可以通过指定

    model中的行列数来获取任一项数据,可以得到与数据项一一对应的那个index。

    QModelIndex index = model->index(row, column, ...);

    Model为简单的,单级的数据结构如list与tables提供了接口,它们如上面代码所显示的那样,不再需要别的信息被提供。当我们在获取一个model index时,我们需要提供另外的信息。

    QTreeView - zhengjiu_520 - !snows snowy world!

    上图代表一个基本的table model,它的每一项用一对行列数来定位。通过行列数,可以获取代表一个数据项的model index .

    QModelIndex indexA = model->index(0, 0, QModelIndex());

     QModelIndex indexB = model->index(1, 1, QModelIndex());

     QModelIndex indexC = model->index(2, 1, QModelIndex());

    一个model的顶级项,由QModelIndex()取得,它们上式被用作父项。

    父项

    类似于表的接口在搭配使用table或list view时理想的,这种行列系统与view显示的方式是确切匹配的。

    然则,像tree views这种结构需要model提供更为灵活的接口来访问数据项。每个数据项可能是别的项的

    父项,上级的项可以获取下级项的列表。

    当获取model中数据项的index时,我们必须指定关于数据项的父项的信息。在model外部,引用一个数据

    项的唯一方法就是通过model index,因此需要在求取model index时指定父项的信息。

    QModelIndex index = model->index(row, column, parent);

    QTreeView - zhengjiu_520 - !snows snowy world!

    上图中,A项和C项作为model中顶层的兄弟项:

     QModelIndex indexA = model->index(0, 0, QModelIndex());

     QModelIndex indexC = model->index(2, 1, QModelIndex());

    A有许多孩子,它的一个孩子B用以下代码获取:

    QModelIndex indexB = model->index(1, 0, indexA);

    项角色

    model中的项可以作为各种角色来使用,这允许为不同的环境提供不同的数据。举例来说,Qt::DisplayRole被用于访问一个字符串,它作为文本会在view中显示。典型地,每个数据项都可以为许多不同的角色提供数据,标准的角色在Qt::ItemDataRole中定义。我们可以通过指定model index与角色来获取我们需要的数据:

    QVariant value = model->data(index, role);

    QTreeView - zhengjiu_520 - !snows snowy world!

    角色指出了从model中引用哪种类型的数据。views可以用不同的形式显示角色,因此为每个角色提供正确

    的信息是非常重要的。通过为每个角色提供适当数据,model也为views和delegates提供了暗示,如何正确地

    把这些数据项显给用户。不同的views可以自由地解析或忽略这些数据信息,对于特殊的场合,也可以定义

    一些附加的角色。

    概念总结:

    1,Model indexes为views与delegages提供model中数据项定位的信息,它与底层的数据结构无关。

    2,通过指定行,列数,父项的model index来引用数据项。

    3,依照别的组件的要求,model indexes被model构建。

    4,使用index()时,如果指定了有效的父项的model index,那么返回得到的model index对应于父项的某个孩子。

    5,使用index()时,如果指定了无效的父项的model index,那么返回得到的model index对应于顶层项的某个孩子。

    6, 角色对一个数据项包含的不同类型的数据给出了区分。

    使用Model Indexes

    QDirModel *model = new QDirModel;

         QModelIndex parentIndex = model->index(QDir::currentPath());

         int numRows = model->rowCount(parentIndex);

     for (int row = 0; row < numRows; ++row)

     {

             QModelIndex index = model->index(row, 0, parentIndex);

             tring text = model->data(index, Qt::DisplayRole).toString();

             // Display the text in a widget.

         }

    以上的例子说明了从model中获取数据的基本原则:

    1,model的尺寸可以从rowCount()与columnCount()中得出。这些函数通常都需要一个表示父项的model index。

    2,model indexes用来从model中访问数据项,数据项用行,列,父项model index定位。

    3, 为了访问model顶层项,可以使用QModelIndex()指定。

    4, 数据项为不同的角色提供不同的数据。为了获取数据,除了model index之外,还要指定角色。

     

    Qt Model/View 学习笔记 (四)

    清源游民 gameogre@gmail.com

    创建新的Models

    介绍

    model/view组件之间功能的分离,允许创建model利用现成的views。这也可以使用标准的功能 图形用户接口组件像QListView,QTableView和QTreeView来显示来自各种数据源的数据为。

    QAbstractListModel类提供了非常灵活的接口,允许数据源以层次结构的形式来管理信息,也允许以某种

    方式对数据进行插入、删除、修改和存储。它也提供了对拖拽操作的支持。

    QAbstractListModel与QAbstractTableModel为简单的非层次结构的数据提供了接口,对于比较简单的list和table models来说,这是不错的一个开始点。

    设计一个Model

    当我们为存在的数据结构新建一个model时,首先要考虑的问题是应该选用哪种model来为这些数据提供接口。

    假如数据结构可以用数据项的列表或表来表示,那么可以考虑子类化QAbstractListModel或QAbstractTableModel

    ,既然这些类已经合理地对许多功能提供缺省实现。

    然而,假如底层的数据结构只能表示成具有层次结构的树型结构,那么必须得子类化QAbstractItemModel。

    无论底层的数据结构采取何种形式,在特定的model中实现标准的QAbstractItemModel API总是一个不错的主意,这使得可以使用更自然的方式对底层的数据结构进行访问。这也使得用数据构建model 更为容易,其他

    的model/view组件也可以使用标准的API与之进行交互。

    一个只读model示例

    这个示例实现了一个简单的,非层次结构的,只读的数据model,它基于QStringistModel类。它有一个QStringList作为它内部的数据源,只实现了一些必要的接口。为了简单化,它子类化了QAbstractListModel,这个基类提供了合理的缺省行为,对外提供了比QAbstractItemModel更为简单的接口。当我们实现一个model时,不要忘了QAbstractItemModel本身不存储任何数据,它仅仅提供了给views访问

    数据的接口。

    class StringListModel : public QAbstractListModel

     {

         Q_OBJECT

     public:

         StringListModel(const QStringList &strings, QObject *parent = 0)

             : QAbstractListModel(parent), stringList(strings) {}

         int rowCount(const QModelIndex &parent = QModelIndex()) const;

         QVariant data(const QModelIndex &index, int role) const;

         QVariant headerData(int section, Qt::Orientation orientation,

                             int role = Qt::DisplayRole) const;

     private:

         QStringList stringList;

     };

    除了构造函数,我们仅需要实现两个函数:rowCount()返回model中的行数,data()返回与特定model index对应的数据项。具有良好行为的model也会实现headerData(),它返回tree和table views需要的,在标题中显示的数据。

    因为这是一个非层次结构的model,我们不必考虑父子关系。假如model具有层次结构,我们也应该实现index()与parent()函数。

    Model的尺寸

    我们认为model中的行数与string list中的string数目一致:

    int StringListModel::rowCount(const QModelIndex &parent) const

     {

         return stringList.count();

     }

    在缺省情况下,从QAbstractListModel派生的model只具有一列,因此不需要实现columnCount()。

    Model 标题与数据

     QVariant StringListModel::data(const QModelIndex &index, int role) const

     {

         if (!index.isValid())

             return QVariant();

         if (index.row() >= stringList.size())

             return QVariant();

         if (role == Qt::DisplayRole)

             return stringList.at(index.row());

         else

             return QVariant();

     }

    QVariant StringListModel::headerData(int section, Qt::Orientation orientation,

                                          int role) const

     {

         if (role != Qt::DisplayRole)

             return QVariant();

         if (orientation == Qt::Horizontal)

             return QString("Column %1").arg(section);

         else

             return QString("Row %1").arg(section);

     }

    一个数据项可能有多个角色,根据角色的不同输出不同的数据。上例中,model中的数据项只有一个角色 ,

    DisplayRole,然而我们也可以重用提供给DisplayRole的数据,作为别的角色使用,如我们可以作为ToolTipRole来用。

    可编辑的model

    上面我们演示了一个只读的model,它只用于向用户显示,对于许多程序来说,可编辑的list model可能更有用。我们只需要给只读的model提供另外两个函数flags()与setData()的实现。下列函数声明被添加到类定义中:

         Qt::ItemFlags flags(const QModelIndex &index) const;

         bool setData(const QModelIndex &index, const QVariant &value,

                      int role = Qt::EditRole);

    让model可编辑

    delegate会在创建编辑器之前检查数据项是否是可编辑的。model必须得让delegate知道它的数据项是可

    编辑的。这可以通过为每一个数据项返回一个正确的标记得到,在本例中,我们假设所有的数据项都是

    可编辑可选择的:

    Qt::ItemFlags StringListModel::flags(const QModelIndex &index) const

     {

         if (!index.isValid())

             return Qt::ItemIsEnabled;

         return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;

     }

    我们不必知道delegate执行怎样实际的编辑处理过程,我们只需提供给delegate一个方法,delegate会使用它对model中的数据进行设置。这个特殊的函数就是setData():

    bool StringListModel::setData(const QModelIndex &index,

                                   const QVariant &value, int role)

     {

         if (index.isValid() && role == Qt::EditRole) {

             stringList.replace(index.row(), value.toString());

             emit dataChanged(index, index);

             return true;

         }

         return false;

     }

    当数据被设置后,model必须得让views知道一些数据发生了变化,这可通过发射一个dataChanged() 信号实现。

    因为只有一个数据项发生了变化,因此在信号中说明的变化范围只限于一个model index。

    插入,删除行

    在model中改变行数与列数是可能的。当然在本列中,只考虑行的情况,我们只需要重新实现插入、删除

    的函数就可以了,下面应在类定义中声明:

         bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());

         bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());

    既然model中的每行对应于列表中的一个string,因此,insertRows()函数在string list  中指定位置插入一个空string,

    父index通常用于决定model中行列的位置,本例中只有一个单独的顶级项,困此只需要在list中插入空string。

    bool StringListModel::insertRows(int position, int rows, const QModelIndex &parent)

     {

         beginInsertRows(QModelIndex(), position, position+rows-1);

         for (int row = 0; row < rows; ++row) {

             stringList.insert(position, "");

         }

         endInsertRows();

         return true;

     }

    beginInsertRows()通知其他组件行数将会改变。endInsertRows()对操作进行确认与通知。

    返回true表示成功。

    删除操作与插入操作类似:

    bool StringListModel::removeRows(int position, int rows, const QModelIndex &parent)

     {

         beginRemoveRows(QModelIndex(), position, position+rows-1);

         for (int row = 0; row < rows; ++row) {

             stringList.removeAt(position);

         }

         endRemoveRows();

         return true;

     }

    Qt Model/View 学习笔记 (五)

    清源游民 gameogre@gmail.com

    View 类

    概念

    在model/view架构中,view从model中获得数据项然后显示给用户。数据显示的方式不必与model提供的表示方式相同,可以与底层存储数据项的数据结构完全不同。

    内容与显式的分离是通过由QAbstractItemModel提供的标准模型接口,由QAsbstractItemview提供的标准视图接口共同实现的。普遍使用model index来表示数据项。view负责管理从model中读取的数据的外观布局。

    它们自己可以去渲染每个数据项,也可以利用delegate来既处理渲染又进行编辑。

    除了显示数据,views也处理数据项的导航,参与有关于数据项选择的部分功能。view也实现一些基本的用户接口特性,如上下文菜单与拖拽功能。view也为数据项提供了缺省的编程功能,也可搭配delegate实现更为特殊的定制编辑的需求。

    一个view创建时必不需要model,但在它能显示一些真正有用的信息之前,必须提供一个model。view通过使用

    selections来跟踪用户选择的数据项。每个view可以维护单独使用的selections,也可以在多个views之间共享。有些views,如QTableView和QTreeView,除数据项之外也可显示标题(Headers),标题部分通过一个view来实现,QHeaderView。标题与view一样总是从相同的model中获取数据。从 model中获取数据的函数是QabstractItemModel::headerDate(),一般总是以表单的形式中显示标题信息。可以从QHeaderView子类化,以实现更为复杂的定制化需求。

    使用现成的view

    Qt提供了三个现成的view 类,它们能够以用户熟悉的方式显示model中的数据。QListView把model中的数据项以一个简单的列表的形式显示,或是以经典的图标视图的形式显示。QTreeView把model中的数据项作为具有层次结构的列表的形式显示,它允许以紧凑的深度嵌套的结构进行显示。QTableView却是把model中的数据项以表格的形式展现,更像是一个电子表格应用程序的外观布局。

    QTreeView - zhengjiu_520 - !snows snowy world!

    以上这些标准view的行为足以应付大多数的应用程序,它们也提供了一些基本的编辑功能,也可以定制特殊的需求。

    使用model

    以前的例子中创建过一个string list model,可以给它设置一些数据,再创建一个view把model中的内容展示出来:

    int main(int argc, char *argv[])

     {

       QApplication app(argc, argv);

     // Unindented for quoting purposes:

     QStringList numbers;

     numbers << "One" << "Two" << "Three" << "Four" << "Five";

     QAbstractItemModel *model = new StringListModel(numbers);

     //要注意的是,这里把StringListModel作为一个QAbstractItemModel来使用。这样我们就可以

     //使用model中的抽象接口,而且如果将来我们用别的model代替了当前这个model,这些代码也会照样工作。

     //QListView提供的列表视图足以满足当前这个model的需要了。

     QListView *view = new QListView;

     view->setModel(model);

      view->show();

      return app.exec();

    }

    QTreeView - zhengjiu_520 - !snows snowy world!

    view会渲染model中的内容,通过model的接口来访问它的数据。当用户试图编辑数据项时,view会使用缺省的delegate来提供一个编辑构件。

    一个model,多个views

    为多个views提供相同的model是非常简单的事情,只要为每个view设置相同的model。

         QTableView *firstTableView = new QTableView;

         QTableView *secondTableView = new QTableView;

         firstTableView->setModel(model);

         secondTableView->setModel(model);

    在model/view架构中信号、槽机制的使用意味着model中发生的改变会传递中联结的所有view中,这保证了

    不管我们使用哪个view,访问的都是同样的一份数据。

    QTreeView - zhengjiu_520 - !snows snowy world!

    上面的图展示了一个model上的两个不同的views,尽管在不同的view中显示的model中的数据是一致的,每个

    view都维护它们自己的内部选择模型,但有时候在某些情况下,共享一个选择模型也是合理的。

    处理数据项的选择

    view中数据项选择机制由QItemSelectionModel类提供。所有标准的view缺省都构建它们自己的选择模型,

    以标准的方式与它们交互。选择模型可以用selectionModel()函数取得,替代的选择模型也可以通过

    setSelectionModel()来设置。当我们想在一个model上提供多个一致的views时,这种对选择模型的控制能力非常有用。通常来讲,除非你子类化一个model或view,你不必直接操纵selections的内容。

    多个views之间共享选择

    接着上边的例子,我们可以这样:

    secondTableView->setSelectionModel(firstTableView->selectionModel());

    现在所有views都在同样的选择模型上操作,数据与选择项都保持同步。

    QTreeView - zhengjiu_520 - !snows snowy world!

    上面的例子中,两个view的类型是相同的,假如这两个view类型不同,那么所选择的数据项在每个view

    中的表现形式会有很大的不同。例如,在一个table view中一个连续的选择,在一个tree view中表现出

    来的可能会是几个高亮的数据项片断的组合。

    Qt Model/View 学习笔记 (六)

    清源游民 gameogre@gmail.com

    在views中选择数据项

    概念

    用于新的view类中的选择模型比Qt3中的模型有了很大的改进。它为基于model/view架构的选择提供了更为全面的描述。尽管对提供了的views来说,负责操纵选择的标准类已经足以应付,但是你也可以创建特定的选择模型来满足你特殊的需求。

    关于在view被选择的数据项的信息保持在QItemSelectionModel类的实例中。它也为每个独立的model中的数据项维护model indexes信息,与任何views都关联关系。既然一个model可用于多个views,那么在多个views之间共享选择信息也是可以做到的,这使得多个views可以以一致的方式进行显示。

    选择由多个选择范围组成。通过仅仅记录开始model indexes与结束model indexes,最大化地记录了可以选择的范围。非连续选择数据项由多个选择范围来描述。选择模型记录model indexes的集合来描述一个选择。最近选择的数据项被称为current selection。应用程序可以通过使用某种类型的选择命令来修改选择的效果。

    在进行选择操作时,可以把QItemSelectionModel看成是model中所有数据项选择状态的一个记录。一旦建立一个选择模型,所有项的集合都可以选择,撤消选择,或者选择状态进行切换而不需要知道哪个数据项是否已经被选择过。所有被选择的项的indexes在任何时候都可以得到,通过信号槽机制可以通知别的组件发生的变化。

    使用选择模型

    标准view类提供了缺省的选择模型,它们可以在大次数程序中使用。一个view中的选择模型可以通过调用view的函数selectionModel()取得,也可以通过setSelectionModel()在多个views之间共享选择模型,因此总的来说构建一个新的模型一般情况不太必要。

    通过给QItemSelection指定一个model,一对model indexes,可以创建一个选择。indexes的用法依赖于给定的model,这两个indexes被解释成选择的区块中的左上角项和右下角项。model中的项的选择服从于选择模型。

    选择项

    构建一个table model ,它有32个项,用一个table view进行显示:

         TableModel *model = new TableModel(8, 4, &app);

         QTableView *table = new QTableView(0);

         table->setModel(model);

         QItemSelectionModel *selectionModel = table->selectionModel();

         QModelIndex topLeft;

         QModelIndex bottomRight;

         topLeft = model->index(0, 0, QModelIndex());

         bottomRight = model->index(5, 2, QModelIndex());

        

          QItemSelection selection(topLeft, bottomRight);

         selectionModel->select(selection, QItemSelectionModel::Select);

    结果如下:

    QTreeView - zhengjiu_520 - !snows snowy world!

    读取选择状态

    存储在选择模型中indexes可以用selectionIndexes()函数来读取。它返回一个未排序的model indexes列表,我们可以遍历它,如果我们知道他们关联于哪个model的话。

        QModelIndexList indexes = selectionModel->selectedIndexes();

         QModelIndex index;

         foreach(index, indexes) {

             QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());

             model->setData(index, text);

         }

    选择模型在选择发生变化时会发出信号。这用于通知别的组件包括整体与当前焦点项所发生的变化。我们可以连接selectionChanged()信号到一个槽,检查当信号产生时哪些项被选择或被取消选择。这个槽被调用时带有两个参数,它们都是QItemSelection对象,一个包含新被选择的项,另一个包含新近被取消选择的项。下面的代码演示了给新选择的项添加数据内容,新近被取消选择的项的内容被清空。

    void MainWindow::updateSelection(const QItemSelection &selected,

         const QItemSelection &deselected)

     {

         QModelIndex index;

         QModelIndexList items = selected.indexes();

         foreach (index, items) {

             QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());

             model->setData(index, text);

         }

         items = deselected.indexes();

         foreach (index, items)

          model->setData(index, "");

     }

    也可以通过响应currentChanged()信号来跟踪当前焦点项.对应的槽就有两个接收参数,一个表示之前的焦点,另一个表示当前的焦点。

    void MainWindow::changeCurrent(const QModelIndex &current,

         const QModelIndex &previous)

     {

         statusBar()->showMessage(

             tr("Moved from (%1,%2) to (%3,%4)")

                 .arg(previous.row()).arg(previous.column())

                 .arg(current.row()).arg(current.column()));

     }

    更新选择

    选择指令是通过选择标志提供的,它被定义在QItemSelectionModel::SelectionFlag中。常用的有Select标记,Toggle标记,Deselect标记,Current标记,Clear标记,其意义一目了然。沿上面例子的结果执行以下代码:

         QItemSelection toggleSelection;

         topLeft = model->index(2, 1, QModelIndex());

         bottomRight = model->index(7, 3, QModelIndex());

         toggleSelection.select(topLeft, bottomRight);

         selectionModel->select(toggleSelection, QItemSelectionModel::Toggle);

    结果如下:

    QTreeView - zhengjiu_520 - !snows snowy world!

    缺省情况下,选择指令只针对单个项(由model indexes指定)。然而,选择指令可以通过与另外标记的结合来改变整行和整列。举例来说,假如你只使用一个index来调用select(),但是用Select标记与Rows标记的组合,那么包括那个项的整行都将被选择。看以下示例:

         QItemSelection columnSelection;

         topLeft = model->index(0, 1, QModelIndex());

         bottomRight = model->index(0, 2, QModelIndex());

         columnSelection.select(topLeft, bottomRight);

         selectionModel->select(columnSelection,

         QItemSelectionModel::Select | QItemSelectionModel::Columns);

         QItemSelection rowSelection;

         topLeft = model->index(0, 0, QModelIndex());

         bottomRight = model->index(1, 0, QModelIndex());

         rowSelection.select(topLeft, bottomRight);

         selectionModel->select(rowSelection,

         QItemSelectionModel::Select | QItemSelectionModel::Rows);

    结果如下

    QTreeView - zhengjiu_520 - !snows snowy world!

    选择模型中所有项

    为了选择model中的所有项,必须先得创建一个选择,它包括当前层次上的所有项:

         QModelIndex topLeft = model->index(0, 0, parent);

         QModelIndex bottomRight = model->index(model->rowCount(parent)-1,

          model->columnCount(parent)-1, parent);

        QItemSelection selection(topLeft, bottomRight);

         selectionModel->select(selection, QItemSelectionModel::Select);

    顶级index可以这样:

    QModelIndex parent = QModelIndex();

    对具有层次结构的model来说,可以使用hasChildren()函数来决定给定项是否是其它项的父项。

     

    Qt Model/View 学习笔记 (七)

    清源游民 gameogre@gmail.com

    Delegate  类

    概念

    与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件。一般来讲, view负责把数据展示

    给用户,也处理用户的输入。为了获得更多的灵性性,交互通过delegagte执行。它既提供输入功能又负责渲染view中的每个数据项。 控制delegates的标准接口在QAbstractItemDelegate类中定义。Delegates通过实现paint()和sizeHint()以达到渲染内容的目的。然而,简单的基于widget的delegates,可以从QItemDelegate子类化,而不是QAbstractItemDelegate,这样可以使用它提供的上述函数的缺省实现。delegate可以使用widget来处理编辑过程,也可以直接对事件进行处理。

    使用现成的delegate

    Qt提供的标准views都使用QItemDelegate的实例来提供编辑功能。它以普通的风格来为每个标准view渲染数据项。这些标准的views包括:QListView,QTableView,QTreeView。所有标准的角色都通过标准views包含的缺省delegate进行处理。一个view使用的delegate可以用itemDelegate()函数取得,而setItemDelegate() 函数可以安装一个定制delegate。

    一个简单的delegate

    这个delegate使用QSpinBox来提供编辑功能。它主要想用于显示整数的models上。尽管我们已经建立了一个基于整数的table model,但我们也可以使用QStandardItemModel,因为delegate可以控制数据的录入。我们又建了一个table view来显示model的内容,用我们定制的delegate来编辑。

    QTreeView - zhengjiu_520 - !snows snowy world!

    我们从QItemDelegate子类化,这样可以利用它缺省实现的显示功能。当然我们必需提供函数来管理用于编辑的widget:

    class SpinBoxDelegate : public QItemDelegate

     {

         Q_OBJECT

     public:

         SpinBoxDelegate(QObject *parent = 0);

         QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,

                               const QModelIndex &index) const;

         void setEditorData(QWidget *editor, const QModelIndex &index) const;

         void setModelData(QWidget *editor, QAbstractItemModel *model,

                           const QModelIndex &index) const;

         void updateEditorGeometry(QWidget *editor,

             const QStyleOptionViewItem &option, const QModelIndex &index) const;

     };

    需要注意的是,当一个delegate创建时,不需要安装一个widget,只有在真正需要时才创建这个用于编辑的widget。

    提供编辑器

    在这个例子中,当table view需要提供一个编辑器时,它要求delegate提供一个可用于编辑的widget,它应该适用于当前正被修改的数据项。这正是createEditor()函数应该实现的:

    QWidget *SpinBoxDelegate::createEditor(QWidget *parent,

         const QStyleOptionViewItem &/* option */,

         const QModelIndex &/* index */) const

     {

         QSpinBox *editor = new QSpinBox(parent);

         editor->setMinimum(0);

         editor->setMaximum(100);

         return editor;

     }

    我们不需要跟踪这个widget的指针,因为view会在不需要时销毁这个widget。我们也给编辑安装了delegate缺省的事件过滤器,这提供了用户期望的标准编辑快捷键。view通过我们定义相应的函数来保证编辑器的数据与几何布局被正确的设置。我们也可以根据不同的model index来创建不同的编辑器,比如,我们有一列整数,一列字符串,我们可以根据哪种列被编辑来创建一个QSpinBox或是QLineEdit。delegate必需提供一个函数把model中的数据拷贝到编辑器中。

    void SpinBoxDelegate::setEditorData(QWidget *editor,

                                         const QModelIndex &index) const

     {

         int value = index.model()->data(index, Qt::DisplayRole).toInt();

         QSpinBox *spinBox = static_cast<QSpinBox*>(editor);

         spinBox->setValue(value);

     }

    向model提交数据

    这需要我们实现另外一个函数setModelData():

    void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,

                                        const QModelIndex &index) const

     {

         QSpinBox *spinBox = static_cast<QSpinBox*>(editor);

         spinBox->interpretText();

         int value = spinBox->value();

         model->setData(index, value);

     }

    标准的QItemDelegate类当它完成编辑时会发射closeEditor()信号来通知view。view保证编辑器widget关闭与销毁。本例中我们只提供简单的编辑功能,因此不需要发送个信号。

    更新编辑器几何布局

    delegate负责管理编辑器的几何布局。这些几何布局信息在编辑创建时或view的尺寸位置发生改变时,

    都应当被提供。幸运的是,view通过一个view option可以提供这些必要的信息。

     void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,

         const QStyleOptionViewItem &option, const QModelIndex &/* index */) const

     {

         editor->setGeometry(option.rect);

     }

    编辑提示

    编辑完成后,delegate会给别的组件提供有关于编辑处理结果的提示,也提供用于后续编辑操作的一些提示。

    这可以通过发射带有某种hint的closeEditor()信号完成。这些信号会被安装在spin box上的缺省的QItemDelegate事件过滤器捕获。对这个缺省的事件过滤来讲,当用户按下回车键,delegate会对model中的数据进行提交,并关闭spin box。

    我们可以安装自己的事件过滤器以迎合我们的需要,例如,我们可以发射带有EditNextItem hint的

    closeEditor()信号来实现自动开始编辑view中的下一项。

    展开全文
  • K210学习记录(3)——kmodel生成与使用

    千次阅读 多人点赞 2020-12-03 20:55:26
    0、引言 该博客仅作为学习K210单片机KPU跑目标检测模型记录,本人新人小白,本文旨在备忘,如有错误,还望指出,谢谢。 1、模型转换 1.1、首先需要下载NNCase工具箱,各版本下载地址 ...ncc yolo.tflite yolo.kmodel -

    0、引言

    该博客仅作为学习K210单片机KPU跑目标检测模型记录,本人新人小白,本文旨在备忘,如有错误,还望指出,谢谢。
    硬件:Sipeed Maix Dock开发板
    软件:MaixPy IDE,NNCase Converter v0.1.0 RC5(模型转换工具)
    相关工具及软件点击这里不需积分下载

    1、模型转换

    1.1、首先需要下载NNCase工具箱,各版本下载地址
    1.2、有关nnc的使用,在Windows下首先在运行中,输入CMD,打开命令行窗口
    1.3、使用cd命令,到nnc的根目录下
    1.4、后使用nnc相关命令行进行操作,命令行说明可以参考
    在将yolo.tflite模型放到ncc根目录下后,使用以下命令进行转换

    ncc yolo.tflite yolo.kmodel -i tflite -o k210model --dataset images
    

    其中yolo.tflite为ncc工具根目录下的待转换模型,yolo.kmodel为转换完成的模型名称(提前设定),-i tflite代表输入模型格式,而-o k210model则代表输出模型模式,–dataset images代表量化图片所存放的文件夹,images是文件夹名,一般放入训练集图片即可。
    最终即可在ncc根目录下找到转换完成的kmodel文件
    在这里插入图片描述

    同时,你也可以使用QT版ncc转换工具,目前仅支持tflift格式的模型文件
    在这里插入图片描述

    2、模型使用

    2.1、检查模型

    通过上述步骤得到kmodel文件后,将其拷贝进FAT32格式的TF卡中(可以不用格式化),后将TF卡插入K210开发板
    并使用以下代码进行测试。如成功读取到TF卡中的模型文件,液晶屏上将显示模型地址及模型尺寸。如下图所示

    from Maix import GPIO, I2S, FFT
    import image, lcd, math,sensor,time
    import KPU as kpu
    
    #初始化液晶屏
    lcd.init(freq=15000000)
    lcd.clear()
    
    #加载SD卡中的模型
    task = kpu.load("/sd/yolo.kmodel")
    ##测试模型是否加载成功,如成功会返回模型地址和模型尺寸
    lcd.draw_string(1, 1, str(task), lcd.RED, lcd.BLACK)
    

    在这里插入图片描述

    其中kpu.load()函数的使用说明详见此,博客地址
    在这里插入图片描述
    源代码见此

    STATIC mp_obj_t py_kpu_class_load(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
    {
        int err = 0;
        uint32_t model_size;
        py_kpu_net_obj_t  *o = m_new_obj_with_finaliser(py_kpu_net_obj_t);
        o->base.type = &py_kpu_net_obj_type;
    
        if(mp_obj_get_type(pos_args[0]) == &mp_type_int)
        {	//load from flash address
            mp_int_t model_addr = mp_obj_get_int(pos_args[0]);
    
            if(model_addr <= 0)//TODO: address of code end
            {
                m_del(py_kpu_net_obj_t, o,sizeof(py_kpu_net_obj_t));
                mp_raise_ValueError("[MAIXPY]kpu: model_addr must > 0 ");
                return mp_const_false;
            }
    
            o->model_addr = mp_obj_new_int(model_addr);
            o->model_path = mp_const_none;
    		sipeed_kpu_err_t ret = sipeed_kpu_model_load(&o->kmodel_ctx, model_addr, NULL, &model_size);
            if(ret != SIPEED_KPU_ERR_NONE)
            {
                err = ret; //load error
                goto error;
            }
        }
        else if(mp_obj_get_type(pos_args[0]) == &mp_type_str)
        {
            const char *path = mp_obj_str_get_str(pos_args[0]);
    
            o->model_path = mp_obj_new_str(path,strlen(path));
            o->model_addr = mp_const_none;
    
            // if(NULL != strstr(path,".bin"))
            // {
            //     err=model_init(kpu_task,path);
            //     if( err != 0 )
            //     {
            //         model_deinit(kpu_task);
            //         goto error;
            //     }
    
            // }
            // else
            if( (NULL != strstr(path,".kmodel")) || (NULL != strstr(path,".smodel")) || (NULL != strstr(path,".emodel")) )
            {
                int ret = sipeed_kpu_model_load(&o->kmodel_ctx, 0, path, &model_size);
                if(ret != SIPEED_KPU_ERR_NONE)
                {
                    err = ret;
                    goto error;
                }
            }
            else
            {   
                m_del(py_kpu_net_obj_t, o,sizeof(py_kpu_net_obj_t));
                mp_raise_ValueError("[MAIXPY]kpu: model format don't match, only supply .kmodel ");
                return mp_const_false;
            }
            
        }
        else
        {
            m_del(py_kpu_net_obj_t, o,sizeof(py_kpu_net_obj_t));
            mp_raise_TypeError("[MAIXPY]kpu: only accept int or string");
            return mp_const_false;
        }    
        o->net_args = mp_const_none;
        o->net_deinit = mp_const_none;
        o->model_size = mp_obj_new_int(model_size);
        o->max_layers = mp_obj_new_int(sipeed_kpu_model_get_layer_num(o->kmodel_ctx));
    
        return MP_OBJ_FROM_PTR(o);
    
    error:
    {
        char* err_msg = get_kpu_err_str(err);
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "[MAIXPY]kpu: load error:%d, %s", err, err_msg));
    }
    }
    
    STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_kpu_class_load_obj, 1, py_kpu_class_load);
    

    在确认K210单片机能正确识别到tf卡中的kmodel后,我们就可以进行下一步的工作了。

    2.2、使用模型

    from Maix import GPIO, I2S, FFT
    import image, lcd, math,sensor,time
    import KPU as kpu
    
    #对摄像头进行初始化
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    #sensor.set_windowing((224, 224))
    #sensor.set_windowing((320, 240))
    sensor.set_brightness(2)
    sensor.set_vflip(1)
    sensor.run(1)
    
    #初始化液晶屏
    lcd.init(freq=15000000)
    lcd.clear()
    
    
    clock = time.clock()
    #标签类名
    classes = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat',
    'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person',
    'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor']
    
    #加载SD卡中的模型
    task = kpu.load("/sd/yolo.kmodel")
    ##测试模型是否加载成功,如成功会返回模型地址和模型尺寸
    #lcd.draw_string(1, 1, str(task), lcd.RED, lcd.BLACK)
    
    #设置锚框大小
    anchor = (1.08, 1.19, 3.42, 4.41, 6.63, 11.38, 9.42, 5.11, 16.62, 10.52)
    #初始化kpu yolo2
    #形参:模型尺寸,mp_obj
    a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
    while(True):
        #用于计算FPS值
        clock.tick()
        #将摄像头采集到的值赋给img这个变量
        img = sensor.snapshot()
        code = kpu.run_yolo2(task, img)
        #打印帧率(115200)
        print(clock.fps())
        if code:
            for i in code:
           		#画矩形框
                a=img.draw_rectangle(i.rect())
             	#显示出来
                a = lcd.display(img)
                for i in code:
                #打印类标签(根据bbox位置)
                    lcd.draw_string(i.x(), i.y(), classes[i.classid()], lcd.RED, lcd.WHITE)
                    lcd.draw_string(i.x(), i.y()+12, '%f1.3'%i.value(), lcd.RED, lcd.WHITE)
        else:
            a = lcd.display(img)
    a = kpu.deinit(task)
    
    

    3、参考资料

    https://github.com/TonyZ1Min/yolo-for-k210
    https://blog.sipeed.com/p/677.html
    https://github.com/kendryte/nncase/tree/master/examples/20classes_yolo

    展开全文
  • 00x: Django models.Model详解

    千次阅读 多人点赞 2019-01-04 12:56:45
    model是对于信息的一种模型封装与定义。它包含了你要存储的必要字段和操作数据的方法。一句话概括就是,每个模型映射了一张数据表。 基本概念: 每个model都是继承于django.db.models.Model 的Python类。 model的每...

    Models
    model是对于信息的一种模型封装与定义。它包含了你要存储的必要字段和操作数据的方法。一句话概括就是,每个模型映射了一张数据表。
    基本概念:

    每个model都是继承于django.db.models.Model 的Python类。

    model的每一个属性对应数据表中的一个字段。

    通过所有的这些,Django提供了一个自动化生成访问数据库的API。

    简单实例
    这个例子定义了Person ,并给它赋予了first_name 和last_name:
    在这里插入图片描述
    其中first_name 和last_name 是model的字段。如你所见,每一个字段被定义为class类的一个属性,而每个属性对应着数据库的一列。

    上面的创建Person ,model模型的过程用SQL语句翻译过来如下:
    在这里插入图片描述
    下面是一些需要注意的问题:

    数据表的名字,myapp_person,自动继承一些model的metadata设定,但是同时支持自定义。

    id字段是自动添加的,但是它同样可以自定义。

    CREATE TABLE这个SQL语句在这个例子中由PostgreSQL来实现,

    使用models
    一旦你定义好了你的模型,你需要告诉Django你将要使用这些models。这就需要秀修改工程目录下的settings.py文件。假设你的model定义在了app名为myapp的models.py 文件中,为了使得Django识别出你要使用这个model,你就需要在settings.py中设定如下:
    在这里插入图片描述
    当你添加新的APP到INSTALLED_APPS中时。需要运行命令python manage.py migrate使设置生效。可供选择的是为了使用git等代码管理软件,你可以先运行python manage.py makemigrations。

    字段
    model最重要的部分而且也是model所需的基础部分是它定义的数据库字段的集合。字段由类的属性来定义。需要注意一点,不要使用和models API冲突的名字来命名字段例如clean,save或者delete。

    例子:

    在这里插入图片描述
    字段类型
    你模型中的每一个字段应该是一个Field类的实例。Django使用字段类来决定一些事:

    列的类型,就是告诉数据库要存储的数据类型是什么。

    默认的HTML插件 ,用以渲染表单字段(例如,)

    基本的验证需求,在Django的admin中和自动生成的表单中使用。

    Django自带了很多内建的字段类型。若Django没有你想要的类型,你可以自己实现。

    字段选项
    每一个字段使用一个确定的字段声明参数集合。例如,CharField(还有它的子类)需要一个max_length参数来声明数据库用于存储字段VARVHAR的个数。

    同样的,还有其他的一些选项可用来设置字段,它们都是可选的。下面介绍几个比较常用的设置选项:

    null:
    若为True,Django会把空数据使用NULL存储在数据库中。默认是False。
    blank:
    若为True,该字段允许为空。默认是False。
    注意它和null的不同。null是纯粹和数据库相关的,而’blank’则是和验证相关的。若一个字段的blank=True,表单的验证将会允许实例带一个空值。反之则不行。
    choices:
    一个可迭代的元祖,用来作为字段内容的选择。若这个给定,默认的表单插件将会变成一个单选框而不是简单的文本字段,并且单选框中的选项数目由给定的choices来限定。
    一个标准的choices列表和下面的形式类似:
    在这里插入图片描述
    每个元组中的第一个元素是要存储在数据库中的内容。第二个元素用于在显示的控件上展示。

    给定一个model的实例,用于显示的choices的值可以通过使用get_FOO_display()方法来获取,例如:
    在这里插入图片描述
    在这里插入图片描述

    default:
    这个选项用于设置该字段的默认值。可以是一个值或者可以是一个可以调用的对象。若是可调用的对象,它会在每次新对象创建的时候调用。
    help_text:
    额外的帮助文本用于显示在widget上。它对文档的生成很有用。
    primary_key:
    若为True,该字段会作为这个model的主键。如果你没有为其他字段声明primary_key=True,Django会自动地添加一个IntegerField字段作为主键。所以如果没有特殊需求,这个选项可以不做设置。
    主键的字段是只读的。如果你改变了现有对象的主键的值然后保存了这个对象,一个新的对象就会和旧的对象并行创建。啥意思呢?如下面的例子所示:
    在这里插入图片描述
    在这里插入图片描述
    unique:
    若为True,该字段必须是整张表中独一无二的

    自动主键字段
    默认情况下,Django给每个模型以下字段:
    在这里插入图片描述
    这是一个自动添加的自增主键。
    如果你想声明一个典型的主键,只需要在对应的字段选项中设置primary_key=True。若Django看到你显式声明了自定义的主键,那么Django就不会为你创建一个自增的id字段。
    每个模型需要明确一个字段作为主键。

    verbose字段
    除了ForeignKey,ManyToManyField和OneToOneField,每个字段都有一个可选的设置参数:详细。若这个选项未给定,Django会使用属性名来定义,用下划线分隔。
    下面的例子中,verbose的名称是”person’s first name”
    在这里插入图片描述

    下面的例子中,verbose的值为”first name”:在这里插入图片描述
    ForeignKey,ManyToManyField和OneToOneField需要第一个参数为model类对象,所以如果要使用verbose_name,需要显式地声明:

    在这里插入图片描述
    一个惯例就是verbose_name的第一个字母一般不写成大写的形式。Django将会自动地将需要首字母大写的地方大写。

    数据库关系
    Django提供了用来描述三种数据库关系的方法,分别是:many-to-one,many-to-many和one-to-one。

    Many-to-one
    使用django.db.models.ForeignKey来定义Many-to-one这种关系。这个类的使用和其他字段的定义一样,也是作为一个属性存在。
    ForeignKey需要一个位置指示参数:当前model相关联的class类名。
    例如,Car 和Manufacturer(制造商)。每个Manufacturer都会制造很多Car,但是每辆Car只属于一家Manufacturer,这样的关系就称为多对一关系。基于此例子,代码可以编写如下:
    在这里插入图片描述
    关于ForeignKey更加详尽的定义链接如下。

    Many-to-many
    举个例子,每个Pizza对象都有多个Topping对象,而多个Topping对象则可以在多个Pizza饼上。代码如下:
    在这里插入图片描述
    ————(复杂的多对多情况遇到的时候再补充)—————–

    One-to-one
    例如,如果你构建了一个名为places的数据库,你应该在数据库中构建相对标准的东西例如地址,电话号码等。然后,如果你想在places的基础上创建一个restaurants 的数据表,这时你就可以直接使用places 所定义好的部分,使用的方式就是一种one-to-one的模式。

    跨APP的model调用
    如果当前app下models.py 文件中的代码想要调用另外一个app中models.py中的model,这也是可以的。做法就是在当前文件中以导入类的方式导入你想要使用的外部的model,然后直接使用即可:
    在这里插入图片描述
    字段的名称限定
    Django对于字段的限制有两个:

    • 字段的名称不能为Python的关键字,这个比较好理解,举例如下:
      在这里插入图片描述
      字段的名称不能包含超过两个下划线,因为这会与Django查找语法起冲突。
      在这里插入图片描述
      SQL的一些保留字如`join,where,select则是可以在model的字段名称中使用的,因为Django在每次SQL查询中避免了可能发生的冲突。

    自定义字段类型
    如果现有的字段无法满足你的需求,你也可以自定义字段。具体的细节参考此链接。

    Meta选项
    通过使用内部类Meta来设置model的元数据,例子如下:
    在这里插入图片描述
    Model的元数据是“任何非字段的数据”,例如ordering的选项,数据表名字(db_table),或者人类可读的单复数名称(verbose_name和verbose_name_plural)。这些都不是Model所必需的,是可选项。
    更多关于Meta的选项点击此链接。

    Model属性
    objects:
    model最重要的属性是Manager。它是提供给Django的数据库查询操作的接口,用于从数据库中获取model实例。若非特别声明Manager,它默认的名字为objects。Manager只能通过model类进行访问,不能通过model实例进行访问。

    Model方法
    为model的对象操作定义一般的“row-level”功能。而Manager方法是对于整张表操作的方法。model的方法应该作用于某一特定的model实例上。
    对于使得业务逻辑的统一来说这是一项很有价值的技术。
    例如,下面的model有一些常用方法:
    在这里插入图片描述
    本例中的最后一个方法是一个property。
    model实例有很多方法的接口,你可以通过重写这些方法来实现自己想要的功能:
    str():
    Python的”魔力函数“,该函数返回一个表示当前对象的字符串。适用于Python或者Django用于将实例显示为纯字符串的形式,这样的情形往往会出现在交互的命令行窗口或者在admin页面中。
    get_absolute_url():
    该函数告诉Django如何计算一个对象的url。Django
    在admin接口中使用该函数,在需要的时候返回对象的url。

    覆写预定义的模型方法
    还有一些其他方法封装了一些你可能会使用到的数据库操作。尤其是save()和delete()方法比较常用。
    你可以自由覆写这些方法来获得自己想要的数据库操作。
    一个典型的使用情景是如果你想要在保存对象到数据库的时候做一些事情,就可以覆写实现。以save()函数为例:
    在这里插入图片描述
    不要忘记在覆写的时候调用父类的方法super().save(*args,**kwargs),这样可以确保对象可以存储到数据库中。如果你忘记了调用父类的方法,那么所有的操作都不会数据库中生效。

    在shell中对数据库进行操作
    Django提供了一个命令行工具,可以将当前项目下的环境,迁移到当前工作环境下。

    在建立了model之后,可以在shell中对model进行操作,执行以下语句,进入shell:
    python manage.py shell
    执行后,进入python命令行模式,此时就可以在这里对你建立的model进行操作了。
    假设我们建立了两个model,定义如下:

    在这里插入图片描述
    数据的插入
    在这里插入图片描述
    以上代码执行后,会在mysql数据库的myapp_grades数据表中插入一条数据。

    数据的修改
    在这里插入图片描述

    数据的删除
    在这里插入图片描述

    关联对象
    在这里插入图片描述

    关联对象 下,对于获取关联对象的机集合,有两个主要任务:

    获得一条Grades数据所对应的所有学生Student
    获得Student所对应的班级Grade

    Model继承
    Django中Model的继承方式几乎和Python中类的继承方式几乎一样。所有的model都继承于实例django.db.models.Model。
    你需要做的决定仅仅是你的父类model的角色:是作为一个抽象类,给子类提供一个通用部分的描述?还是直接作为实例,拥有自己的数据表?以下是三种最常用的类继承模式:

    通常情况下,我们只想使用父类来保存一些你不想在每个子类中都敲一遍的通用信息。该类不会真正对数据库操作,也就是所谓的抽象基类。
    如果你继承了一个现存的模型(可能来自于另外一个app实例)并且想要每个model都有自己的数据表,Multi-table inheritance就是这样做的。
    最后,如果你只是想要修改Python语言级别的model行为而不修改models的字段,你可以使用Proxy models
    抽象基类
    抽象基类在你想要在你的模型中加入一些信息的时候很有用。在元数据中将基类的参数abstract=True,这样,该model就不会被用来创建任何数据表。当它被其他model作为基类时,它的字段将会作为继承它基类的字段。子类中的字段名不能和基类中的字段名一样,否则会报错。下面是一个例子:
    在这里插入图片描述
    Student模型有三个字段,分别是name,age和home_group。
    CommonInfo模型不能被用作是一个正常的Django模型,因为他是一个抽象基类,它不会生成数据库表或者有manager,不能被直接实例化或者保存。

    Meta继承
    当一个抽象基类被创建的时候,Django会声明一些Meta 内部类,若子类没有声明它自己的Meta类,它就会继承父Meta。如果子类想要拓展父Meta类,需要先继承,再拓展:
    在这里插入图片描述
    Django对于抽象基类Meta类做了调整:在使用Meta属性的时候,会设置abstract=False 。这意味着抽象基类的子类不会自动变成抽象类,除非你自己手动将其设置为True,让其成为抽象类。

    展开全文
  • 如何在vue3中优雅地使用v-model

    万次阅读 2020-09-25 20:09:59
    文章目录Vue中的数据绑定v-bindv-bind支持的类型v-bind使用v-modelvue2中v-model用法不使用v-model的双向绑定父组件子组件使用v-model后父组件子组件问题.syncvue2中使用v-model + .sync父组件子组件vue3中v-model的...
  • model.evaluate 用于评估您训练的模型。它的输出是model的acc和loss,而不是对输入数据的预测。 model.predict 实际预测,输入为test sample,输出为label。 在keras中有两个预测函数model.predict_classes(test...
  • 在学习强化学习的过程中,有两个名词早晚会出现在我们面前,就是Model-Based和Model-Free。在一些资料中,我们经常会见到“这是一个Model-Based 的算法”或者“这个方法是典型的Model-Free的算法”的说法。“Model-...
  • model.train()和model.eval()的区别主要在于Batch Normalization和Dropout两层。 model.train() 官方文档 启用 Batch Normalization 和 Dropout。 如果模型中有BN层(Batch Normalization)和 Dropout,需要在训练时...
  • model.train() 启用 Batch Normalization 和 Dropout 如果模型中有BN层(Batch Normalization)和Dropout,需要在训练时添加model.train()。model.train()是保证BN层能够用到每一批数据的均值和方差。对于Dropout,...
  • 区分Model-free和Model-based方法

    千次阅读 2018-11-20 13:28:48
    强化学习方法分为Model-free和Model-based方法,那么这两种方法的区别在哪: 首先我们定义强化学习中的马尔可夫决策过程MDP,用四元组表示&lt;S,A,R,T&gt;&lt;S,A,R,T&gt;: SS:环境的状态空间 ...
  • Vue之v-model原理

    千次阅读 2019-10-22 14:47:45
    目标:1、了解v-model的本质。2、了解v-model的实现原理。 我们知道Vue的核心特性之一是双向绑定,vue的响应式原理是实现了数据->视图,接下来我们要学习视图->数据的原理。 v-model是一个指令,限制在<...
  • model.save()保存了模型的图结构和模型的参数,保存模型的后缀是.hdf5。 model. save_weights ()只保存了模型的参数,并没有保存模型的图结构,保存模型的后缀使用.h5。 所以使用save_weights保存的模型比使用save...
  • sklearn:sklearn.feature_selection的SelectFromModel函数的简介、使用方法之详细攻略 目录 SelectFromModel函数的简介 1、使用SelectFromModel和LassoCV进行特征选择 2、L1-based feature selection 3、...
  • ModelMapper 的高级使用

    万次阅读 2019-05-12 00:19:01
    ModelMapper 高级使用   ModelMapper 是一个 Object To Object 的工具,类似于 MapStruct又不同于 MapStruct。主要原因是 ModelMapper 是利用反射的原理实现的 Object To Object。   ModelMapper 官方API : ...
  • 一、概念 1.v-model可以看成是value+input方法的语法糖。 2.组件的v-model就是value+input方法的语法... 在组件初始化的时候,回去判断当前数据中有没有model属性,如果有就会使用transformModel方法进行model的转...
  • https://github.com/tensorflow/model-optimization/blob/master/tensorflow_model_optimization/g3doc/guide/pruning/pruning_with_keras.ipynb 搬运工 Copyright 2019 The TensorFlow Authors. In[0]:...
  • Spring中Model、ModelMap、ModelAndView理解和具体使用总结

    万次阅读 多人点赞 2018-08-02 19:05:29
    model Map of model names (Strings) to model objects * (Objects). Model entries may not be <code>null, but the * model Map may be <code>null</code> if there is no model data. */ public ...
  • Keras Model模型Keras 中文文档Keras 模型Sequential 顺序模型Sequential使用方法一个简单的Sequential示例构建方法input shape 输入的形状(格式)complication 编译training 训练Model 模型Model 使用方法compile ...
  • keras中获取model各层参数

    千次阅读 2019-12-05 16:48:03
    1、构建一个基础神经网络 from keras.layers import Dense, ...from keras import Sequential,Model from keras.layers import Conv2D,MaxPooling2D,BatchNormalization,Dropout from keras.layers import Average...
  • 特征选择 有很多方法 一、sklearn.feature_selection.SelecFromModel: fit后得到coef_ 或feature_importances_,应用于特征中,小于设定的阈值特征认为不重要,可去除。...SelectFromModel包括:L1-based featur...
  • kaldi中的chain model(LFMMI)详解

    万次阅读 多人点赞 2019-03-10 18:52:42
    chain model的结构 chain model实际上是借鉴了CTC的思想,引入了blank用来吸收不确定的边界。但CTC只有一个blank,而chain model中每一个建模单元都有自己的blank。如下图所示: 对应kaldi中的结构定义为: &...
  • 在利用TensorFlow的TensorBoard对train_on_batch...在讲解train_on_batch之前,先看一下Keras的model.compile函数。下面利用Keras版Faster R-CNN代码进行讲解。示例代码如下: # define the RPN, built on the bas...
  • v-model和:model的区别

    万次阅读 多人点赞 2019-02-21 12:01:12
    v-model是vue.js中内置的双向数据绑定指令, 用于表单控件以外的标签是不起作用的 (即只对表单控件标签的数据双向绑定有效)。 :model相当于v-bind:model的缩写, v-bind动态绑定指令,默认情况下标签自带属性的...
  • TensorFlow中的saved_model模块用于生成冻结图文件,并且saved_model模块封装了平常用的Saver类。与Saver类不同的是,saved_model模块生成的模型文件集成了打标签的操作,可以更方便地部署在生产环境中。 关于为什么...
  • # Train XGBoost model, save to file using pickle, load and make predictions from numpy import loadtxt import xgboost import pickle from sklearn import model_selection from sklearn.metrics import ...
  • The model.evaluatefunction predicts the output for the given input and then computes the metrics function specified in the model.compileand based on y_trueand y_predand returns the compute...
  • keras.model.fit()方法源码解释如下: ``` y: Numpy array of target (label) data (if the model has a single output), or list of Numpy arrays (if the model has multiple outputs). If output ...
  • ModelCheckpoint详解

    万次阅读 多人点赞 2020-10-14 10:30:34
    keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1) ...
  • 首先说明v-model是.sync的一种特殊情况,也就是当prop是value,vm.$emit('update:input'),这个时候就是传统意义上的v-model,也就是说v-modelmodel为prop等于value,event为input的特殊情况。 概念 双向数据...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,781,689
精华内容 712,675
关键字:

model