精华内容
下载资源
问答
  • Transformer-Tensorflow2 用于分类Transformer架构 要求:Tensorflow 2.0
  • 文章目录一、Vision Transformer (ViT)详细信息二、Vision Transformer结构三、Keras实现3.1 相关包3.2 数据读取3.3 声明超参数3.4 使用数据增强方法3.5 计算训练数据的平均值和方差进行归一化3.6 定义multilayer ...

    一、Vision Transformer (ViT)详细信息

    VIT详细信息
    文献←下载An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale
    案例数据集CIFAR-100

    二、Vision Transformer结构

    Transformer已经基本取代RNNs(包括变体LSTM ,GRU),成为自然语言处理(NLP)领域的主流模型。Dosovitskiy等人将该模型迁移到计算机视觉领域,并且尽量减少了对Transformer的更改,因为是分类,所以模型的输出用全连接层代替。由此,Vision Transformer(ViT)应运而生。这是一种用于分类任务的改进Transformer。
    ViT结构如下图所示
    在这里插入图片描述
    原作者的文章可能不太详细。为了便于理解,可参考文献提供的结构:
    Vision Transformers for Remote Sensing Image Classification
    在这里插入图片描述

    三、Keras实现

    代码官方已开源。经过测试,需要Tensorflow2.4、2.5等带有MultiHeadAttention包的版本即可,具体配置请参考该文
    代码按顺序输入即可

    3.1 相关包

    import numpy as np
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    
    #下包非必须,可以注释,后续内容替换为adam梯度优化算法,经过测试效果比原码好
    import tensorflow_addons as tfa 
    

    3.2 数据读取

    # 类别数
    num_classes = 100
    # 数据大小
    input_shape = (32, 32, 3)
    # 读取cifar100数据集
    (x_train, y_train), (x_test, y_test) = keras.datasets.cifar100.load_data()
    
    print(f"x_train 大小: {x_train.shape} - y_train 大小: {y_train.shape}")
    print(f"x_test 大小: {x_test.shape} - y_test 大小: {y_test.shape}")
    

    3.3 声明超参数

    learning_rate = 0.001
    weight_decay = 0.0001
    batch_size = 256
    num_epochs = 100
    image_size = 72  # 改变图形大小
    patch_size = 6  # 输入图片拆分的块大小
    num_patches = (image_size // patch_size) ** 2
    projection_dim = 64
    num_heads = 4
    transformer_units = [
        projection_dim * 2,
        projection_dim,
    ]  # Transformer layers的大小
    transformer_layers = 8
    mlp_head_units = [2048, 1024]  # 输出部分的MLP全连接层的大小
    

    3.4 使用数据增强方法

    data_augmentation = keras.Sequential(
        [
            layers.experimental.preprocessing.Normalization(),
            layers.experimental.preprocessing.Resizing(image_size, image_size),
            layers.experimental.preprocessing.RandomFlip("horizontal"),
            layers.experimental.preprocessing.RandomRotation(factor=0.02),
            layers.experimental.preprocessing.RandomZoom(
                height_factor=0.2, width_factor=0.2
            ),
        ],
        name="data_augmentation",
    )
    

    3.5 计算训练数据的平均值和方差进行归一化

    data_augmentation.layers[0].adapt(x_train)
    

    3.6 定义multilayer perceptron (MLP)

    def mlp(x, hidden_units, dropout_rate):
        for units in hidden_units:
            x = layers.Dense(units, activation=tf.nn.gelu)(x)
            x = layers.Dropout(dropout_rate)(x)
        return x
    

    3.7 定义块

    class Patches(layers.Layer):
        def __init__(self, patch_size):
            super(Patches, self).__init__()
            self.patch_size = patch_size
    
        def call(self, images):
            batch_size = tf.shape(images)[0]
            patches = tf.image.extract_patches(
                images=images,
                sizes=[1, self.patch_size, self.patch_size, 1],
                strides=[1, self.patch_size, self.patch_size, 1],
                rates=[1, 1, 1, 1],
                padding="VALID",
            )
            patch_dims = patches.shape[-1]
            patches = tf.reshape(patches, [batch_size, -1, patch_dims])
            return patches
    

    3.8 数据可视化

    import matplotlib.pyplot as plt
    
    plt.figure(figsize=(4, 4))
    image = x_train[np.random.choice(range(x_train.shape[0]))]
    plt.imshow(image.astype("uint8"))
    plt.axis("off")
    
    resized_image = tf.image.resize(
        tf.convert_to_tensor([image]), size=(image_size, image_size)
    )
    patches = Patches(patch_size)(resized_image)
    print(f"图片大小: {image_size} X {image_size}")
    print(f"切块大小e: {patch_size} X {patch_size}")
    print(f"每个图对应的切块大小: {patches.shape[1]}")
    print(f"每个块对应的元素: {patches.shape[-1]}")
    
    n = int(np.sqrt(patches.shape[1]))
    plt.figure(figsize=(4, 4))
    for i, patch in enumerate(patches[0]):
        ax = plt.subplot(n, n, i + 1)
        patch_img = tf.reshape(patch, (patch_size, patch_size, 3))
        plt.imshow(patch_img.numpy().astype("uint8"))
        plt.axis("off")
    

    3.9 实现Encoding Layer

    class PatchEncoder(layers.Layer):
        def __init__(self, num_patches, projection_dim):
            super(PatchEncoder, self).__init__()
            self.num_patches = num_patches
            self.projection = layers.Dense(units=projection_dim)
            self.position_embedding = layers.Embedding(
                input_dim=num_patches, output_dim=projection_dim
            )
    
        def call(self, patch):
            positions = tf.range(start=0, limit=self.num_patches, delta=1)
            encoded = self.projection(patch) + self.position_embedding(positions)
            return encoded
    

    这里大概率会报错,方法需要声明,方法可见此文

    3.10 构建ViT模型

    def create_vit_classifier():
        inputs = layers.Input(shape=input_shape)
        # 数据增强
        augmented = data_augmentation(inputs)
        # 创建块.
        patches = Patches(patch_size)(augmented)
        # Encode patches.
        encoded_patches = PatchEncoder(num_patches, projection_dim)(patches)
    
        # 创建多个Transformer encoding 块
        for _ in range(transformer_layers):
            # Layer normalization 1.
            x1 = layers.LayerNormalization(epsilon=1e-6)(encoded_patches)
            # 创建多头自注意力机制 multi-head attention layer,这里经过测试Tensorflow2.5可用
            attention_output = layers.MultiHeadAttention(
                num_heads=num_heads, key_dim=projection_dim, dropout=0.1
            )(x1, x1)
            # Skip connection.
            x2 = layers.Add()([attention_output, encoded_patches])
         
            x3 = layers.LayerNormalization(epsilon=1e-6)(x2)
            # MLP.
            x3 = mlp(x3, hidden_units=transformer_units, dropout_rate=0.1)
            # Skip connection 2.
            encoded_patches = layers.Add()([x3, x2])
    
        representation = layers.LayerNormalization(epsilon=1e-6)(encoded_patches)
        representation = layers.Flatten()(representation)
        representation = layers.Dropout(0.5)(representation)
        # 增加MLP.
        features = mlp(representation, hidden_units=mlp_head_units, dropout_rate=0.5)
        # 输出分类.
        logits = layers.Dense(num_classes)(features)
        # 构建
        model = keras.Model(inputs=inputs, outputs=logits)
        model.summary()
        return model
    

    3.11 训练+评估(AdamW可以换成Adam,效果可能还更好)

    #tfa.方法可替换为adam
    def run_experiment(model):
        optimizer = tfa.optimizers.AdamW(
            learning_rate=learning_rate, weight_decay=weight_decay
        )
    
        model.compile(
        # 下述可直接替换为  optimizer='adam',
            optimizer=optimizer,
            loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
            metrics=[
                keras.metrics.SparseCategoricalAccuracy(name="accuracy"),
                keras.metrics.SparseTopKCategoricalAccuracy(5, name="top-5-accuracy"),
            ],
        )
    
        checkpoint_filepath = "/tmp/checkpoint"
        checkpoint_callback = keras.callbacks.ModelCheckpoint(
            checkpoint_filepath,
            monitor="val_accuracy",
            save_best_only=True,
            save_weights_only=True,
        )
    
        history = model.fit(
            x=x_train,
            y=y_train,
            batch_size=batch_size,
            epochs=num_epochs,
            validation_split=0.1,
            callbacks=[checkpoint_callback],
        )
    
        model.load_weights(checkpoint_filepath)
        _, accuracy, top_5_accuracy = model.evaluate(x_test, y_test)
        print(f"Test accuracy: {round(accuracy * 100, 2)}%")
        print(f"Test top 5 accuracy: {round(top_5_accuracy * 100, 2)}%")
    
        return history
    
    
    vit_classifier = create_vit_classifier()
    history = run_experiment(vit_classifier)
    

    四、完整代码

    import numpy as np
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    import matplotlib.pyplot as plt
    #非必须包↓若用adamw则加,实测用keras自带的adam效果更好
    import tensorflow_addons as tfa 
    # 类别数
    num_classes = 100
    # 数据大小
    input_shape = (32, 32, 3)
    # 读取cifar100数据集
    (x_train, y_train), (x_test, y_test) = keras.datasets.cifar100.load_data()
    
    print(f"x_train 大小: {x_train.shape} - y_train 大小: {y_train.shape}")
    print(f"x_test 大小: {x_test.shape} - y_test 大小: {y_test.shape}")
    
    learning_rate = 0.001
    weight_decay = 0.0001
    batch_size = 256
    num_epochs = 100
    image_size = 72  # 改变图形大小
    patch_size = 6  # 输入图片拆分的块大小
    num_patches = (image_size // patch_size) ** 2
    projection_dim = 64
    num_heads = 4
    transformer_units = [
        projection_dim * 2,
        projection_dim,
    ]  # Transformer layers的大小
    transformer_layers = 8
    mlp_head_units = [2048, 1024]  # 输出部分的MLP全连接层的大小
    
    data_augmentation = keras.Sequential(
        [
            layers.experimental.preprocessing.Normalization(),
            layers.experimental.preprocessing.Resizing(image_size, image_size),
            layers.experimental.preprocessing.RandomFlip("horizontal"),
            layers.experimental.preprocessing.RandomRotation(factor=0.02),
            layers.experimental.preprocessing.RandomZoom(
                height_factor=0.2, width_factor=0.2
            ),
        ],
        name="data_augmentation",
    )
    data_augmentation.layers[0].adapt(x_train)
    
    def mlp(x, hidden_units, dropout_rate):
        for units in hidden_units:
            x = layers.Dense(units, activation=tf.nn.gelu)(x)
            x = layers.Dropout(dropout_rate)(x)
        return x
    
    class Patches(layers.Layer):
        def __init__(self, patch_size):
            super(Patches, self).__init__()
            self.patch_size = patch_size
    
        def call(self, images):
            batch_size = tf.shape(images)[0]
            patches = tf.image.extract_patches(
                images=images,
                sizes=[1, self.patch_size, self.patch_size, 1],
                strides=[1, self.patch_size, self.patch_size, 1],
                rates=[1, 1, 1, 1],
                padding="VALID",
            )
            patch_dims = patches.shape[-1]
            patches = tf.reshape(patches, [batch_size, -1, patch_dims])
            return patches
    
    
    
    plt.figure(figsize=(4, 4))
    image = x_train[np.random.choice(range(x_train.shape[0]))]
    plt.imshow(image.astype("uint8"))
    plt.axis("off")
    
    resized_image = tf.image.resize(
        tf.convert_to_tensor([image]), size=(image_size, image_size)
    )
    patches = Patches(patch_size)(resized_image)
    print(f"图片大小: {image_size} X {image_size}")
    print(f"切块大小e: {patch_size} X {patch_size}")
    print(f"每个图对应的切块大小: {patches.shape[1]}")
    print(f"每个块对应的元素: {patches.shape[-1]}")
    
    n = int(np.sqrt(patches.shape[1]))
    plt.figure(figsize=(4, 4))
    for i, patch in enumerate(patches[0]):
        ax = plt.subplot(n, n, i + 1)
        patch_img = tf.reshape(patch, (patch_size, patch_size, 3))
        plt.imshow(patch_img.numpy().astype("uint8"))
        plt.axis("off")
    
    class PatchEncoder(layers.Layer):
        def __init__(self, num_patches, projection_dim):
            super(PatchEncoder, self).__init__()
            self.num_patches = num_patches
            self.projection = layers.Dense(units=projection_dim)
            self.position_embedding = layers.Embedding(
                input_dim=num_patches, output_dim=projection_dim
            )
    #这里call后需要定义get_config函数,命名自拟,文章3.9中给出
        def call(self, patch):
            positions = tf.range(start=0, limit=self.num_patches, delta=1)
            encoded = self.projection(patch) + self.position_embedding(positions)
            return encoded
    
    def create_vit_classifier():
        inputs = layers.Input(shape=input_shape)
        # 数据增强
        augmented = data_augmentation(inputs)
        # Create patches.
        patches = Patches(patch_size)(augmented)
        # Encode patches.
        encoded_patches = PatchEncoder(num_patches, projection_dim)(patches)
    
        # 创建多个Transformer encoding 块
        for _ in range(transformer_layers):
            # Layer normalization 1.
            x1 = layers.LayerNormalization(epsilon=1e-6)(encoded_patches)
            # 创建多头自注意力机制 multi-head attention layer,这里经过测试Tensorflow2.5可用
            attention_output = layers.MultiHeadAttention(
                num_heads=num_heads, key_dim=projection_dim, dropout=0.1
            )(x1, x1)
            # Skip connection.
            x2 = layers.Add()([attention_output, encoded_patches])
         
            x3 = layers.LayerNormalization(epsilon=1e-6)(x2)
            # MLP.
            x3 = mlp(x3, hidden_units=transformer_units, dropout_rate=0.1)
            # Skip connection 2.
            encoded_patches = layers.Add()([x3, x2])
    
        representation = layers.LayerNormalization(epsilon=1e-6)(encoded_patches)
        representation = layers.Flatten()(representation)
        representation = layers.Dropout(0.5)(representation)
        # 增加MLP.
        features = mlp(representation, hidden_units=mlp_head_units, dropout_rate=0.5)
        # 输出分类.
        logits = layers.Dense(num_classes)(features)
        # 构建
        model = keras.Model(inputs=inputs, outputs=logits)
        model.summary()
        return model
    
    #tfa.方法可替换为adam
    def run_experiment(model):
        optimizer = tfa.optimizers.AdamW(
            learning_rate=learning_rate, weight_decay=weight_decay
        )
    
        model.compile(
        # 下述可直接替换为  optimizer='adam',
            optimizer=optimizer,
            loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
            metrics=[
                keras.metrics.SparseCategoricalAccuracy(name="accuracy"),
                keras.metrics.SparseTopKCategoricalAccuracy(5, name="top-5-accuracy"),
            ],
        )
    
        checkpoint_filepath = "/tmp/checkpoint"
        checkpoint_callback = keras.callbacks.ModelCheckpoint(
            checkpoint_filepath,
            monitor="val_accuracy",
            save_best_only=True,
            save_weights_only=True,
        )
    
        history = model.fit(
            x=x_train,
            y=y_train,
            batch_size=batch_size,
            epochs=num_epochs,
            validation_split=0.1,
            callbacks=[checkpoint_callback],
        )
    
        model.load_weights(checkpoint_filepath)
        _, accuracy, top_5_accuracy = model.evaluate(x_test, y_test)
        print(f"Test accuracy: {round(accuracy * 100, 2)}%")
        print(f"Test top 5 accuracy: {round(top_5_accuracy * 100, 2)}%")
    
        return history
    
    
    vit_classifier = create_vit_classifier()
    history = run_experiment(vit_classifier)
    

    五、可视化

    5.1 待切块图

    在这里插入图片描述

    5.2 模型结构参数

    在这里插入图片描述
    就参数量来说,Transformer对内存的占用率还是很大(相对一般的模型)

    展开全文
  • 文本分类不是生成式的任务,因此只使用Transformer的编码部分(Encoder)进行特征提取。如果不熟悉Transformer模型的原理请移步。 网络结构 代码实现 自注意力模型: class TextSlfAttnNet(nn.Module): ''' 自...

    前言

    文本分类不是生成式的任务,因此只使用Transformer的编码部分(Encoder)进行特征提取。如果不熟悉Transformer模型的原理请移步

    网络结构

    在这里插入图片描述

    代码实现

    • 自注意力模型:
    class TextSlfAttnNet(nn.Module):
        ''' 自注意力模型 '''
    
        def __init__(self,
                     config: TextSlfAttnConfig,
                     char_size=5000,
                     pinyin_size=5000):
            super(TextSlfAttnNet, self).__init__()
            # 字向量
            self.char_embedding = nn.Embedding(char_size, config.embedding_size)
            # 拼音向量
            self.pinyin_embedding = nn.Embedding(pinyin_size, config.embedding_size)
            # 位置向量
            self.pos_embedding = nn.Embedding.from_pretrained(
                get_sinusoid_encoding_table(config.max_sen_len, config.embedding_size, padding_idx=0),
                freeze=True)
    
            self.layer_stack = nn.ModuleList([
                EncoderLayer(config.embedding_size, config.hidden_dims, config.n_heads, config.k_dims, config.v_dims, dropout=config.keep_dropout)
                for _ in range(config.hidden_layers)
            ])
    
            self.fc_out = nn.Sequential(
                nn.Dropout(config.keep_dropout),
                nn.Linear(config.embedding_size, config.hidden_dims),
                nn.ReLU(inplace=True),
                nn.Dropout(config.keep_dropout),
                nn.Linear(config.hidden_dims, config.num_classes),
    
            )
    
    
        def forward(self, char_id, pinyin_id, pos_id):
            char_inputs = self.char_embedding(char_id)
            pinyin_iputs = self.pinyin_embedding(pinyin_id)
    
            sen_inputs = torch.cat((char_inputs, pinyin_iputs), dim=1)
            # sentence_length = sen_inputs.size()[1]
            # pos_id = torch.LongTensor(np.array([i for i in range(sentence_length)]))
            pos_inputs = self.pos_embedding(pos_id)
            # batch_size * sen_len * embedding_size
            inputs = sen_inputs + pos_inputs
    
            for layer in self.layer_stack:
                inputs, _ = layer(inputs)
    
            enc_outs = inputs.permute(0, 2, 1)
            enc_outs = torch.sum(enc_outs, dim=-1)
            return self.fc_out(enc_outs)
    
    • 编码层(EncoderLayer):
    class EncoderLayer(nn.Module):
        '''编码层'''
    
        def __init__(self, d_model, d_inner, n_head, d_k, d_v, dropout=0.1):
            '''
    
            :param d_model: 模型输入维度
            :param d_inner: 前馈神经网络隐层维度
            :param n_head:  多头注意力
            :param d_k:     键向量
            :param d_v:     值向量
            :param dropout:
            '''
            super(EncoderLayer, self).__init__()
            self.slf_attn = MultiHeadAttention(n_head, d_model, d_k, d_v, dropout=dropout)
            self.pos_ffn = PositionwiseFeedForward(d_model, d_inner, dropout=dropout)
    
        def forward(self, enc_input, non_pad_mask=None, slf_attn_mask=None):
            '''
    
            :param enc_input:
            :param non_pad_mask:
            :param slf_attn_mask:
            :return:
            '''
            enc_output, enc_slf_attn = self.slf_attn(enc_input, enc_input, enc_input, mask=slf_attn_mask)
            if non_pad_mask is not None:
                enc_output *= non_pad_mask
    
            enc_output = self.pos_ffn(enc_output)
            if non_pad_mask is not None:
                enc_output *= non_pad_mask
            return enc_output, enc_slf_attn
    
    • 多头注意力(MultiHeadAttention
    class MultiHeadAttention(nn.Module):
        '''
            “多头”注意力模型
        '''
    
        def __init__(self, n_head, d_model, d_k, d_v, dropout=0.1):
            '''
    
            :param n_head: “头”数
            :param d_model: 输入维度
            :param d_k: 键向量维度
            :param d_v: 值向量维度
            :param dropout:
            '''
            super(MultiHeadAttention, self).__init__()
    
            self.n_head = n_head
            self.d_k = d_k
            self.d_v = d_v
            # 产生 查询向量q,键向量k, 值向量v
            self.w_qs = nn.Linear(d_model, n_head * d_k)
            self.w_ks = nn.Linear(d_model, n_head * d_k)
            self.w_vs = nn.Linear(d_model, n_head * d_v)
    
            nn.init.normal_(self.w_qs.weight, mean=0, std=np.sqrt(2.0 / (d_model + d_k)))
            nn.init.normal_(self.w_ks.weight, mean=0, std=np.sqrt(2.0 / (d_model + d_k)))
            nn.init.normal_(self.w_vs.weight, mean=0, std=np.sqrt(2.0 / (d_model + d_v)))
    
            self.attention = ScaledDotProductAttention(temperature=np.power(d_k, 0.5))
            self.layer_normal = nn.LayerNorm(d_model)
    
            self.fc = nn.Linear(n_head * d_v, d_model)
            nn.init.xavier_normal_(self.fc.weight)
    
            self.dropout = nn.Dropout(dropout)
    
        def forward(self, q, k, v, mask=None):
            '''
            计算多头注意力
            :param q: 用于产生  查询向量
            :param k: 用于产生  键向量
            :param v:  用于产生 值向量
            :param mask:
            :return:
            '''
            d_k, d_v, n_head = self.d_k, self.d_v, self.n_head
    
            sz_b, len_q, _ = q.size()
            sz_b, len_k, _ = k.size()
            sz_b, len_v, _ = v.size()
    
            residual = q
    
            q = self.w_qs(q).view(sz_b, len_q, n_head, d_k)
            k = self.w_ks(k).view(sz_b, len_k, n_head, d_k)
            v = self.w_vs(v).view(sz_b, len_v, n_head, d_v)
    
            # (n*b) x lq x dk
            q = q.permute(2, 0, 1, 3).contiguous().view(-1, len_q, d_k)
            # (n*b) x lk x dk
            k = k.permute(2, 0, 1, 3).contiguous().view(-1, len_k, d_k)
            # (n*b) x lv x dv
            v = v.permute(2, 0, 1, 3).contiguous().view(-1, len_v, d_v)
    
            # mask = mask.repeat(n_head, 1, 1)  # (n*b) x .. x ..
            #
            output, attn = self.attention(q, k, v, mask=None)
            # (n_heads * batch_size) * lq * dv
            output = output.view(n_head, sz_b, len_q, d_v)
            # batch_size * len_q * (n_heads * dv)
            output = output.permute(1, 2, 0, 3).contiguous().view(sz_b, len_q, -1)
            output = self.dropout(self.fc(output))
            output = self.layer_normal(output + residual)
            return output, attn
    
    • 前馈神经网络(PositionwiseFeedForward
    class PositionwiseFeedForward(nn.Module):
        '''
            前馈神经网络
        '''
    
        def __init__(self, d_in, d_hid, dropout=0.1):
            '''
    
            :param d_in:    输入维度
            :param d_hid:   隐藏层维度
            :param dropout:
            '''
            super(PositionwiseFeedForward, self).__init__()
            self.w_1 = nn.Conv1d(d_in, d_hid, 1)
            self.w_2 = nn.Conv1d(d_hid, d_in, 1)
            self.layer_normal = nn.LayerNorm(d_in)
            self.dropout = nn.Dropout(dropout)
    
        def forward(self, x):
            residual = x
            output = x.transpose(1, 2)
            output = self.w_2(F.relu(self.w_1(output)))
            output = output.transpose(1, 2)
            output = self.dropout(output)
            output = self.layer_normal(output + residual)
            return output
    
    • 位置函数
    def get_sinusoid_encoding_table(n_position, d_hid, padding_idx=None):
        '''
        计算位置向量
        :param n_position:      位置的最大值
        :param d_hid:           位置向量的维度,和字向量维度相同(要相加求和)
        :param padding_idx: 
        :return: 
        '''
    
        def cal_angle(position, hid_idx):
            return position / np.power(10000, 2 * (hid_idx // 2) / d_hid)
    
        def get_posi_angle_vec(position):
            return [cal_angle(position, hid_j) for hid_j in range(d_hid)]
    
        sinusoid_table = np.array([get_posi_angle_vec(pos_i) for pos_i in range(n_position)])
    
        sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2])  # dim 2i
        sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2])  # dim 2i+1
    
        if padding_idx is not None:
            # zero vector for padding dimension
            sinusoid_table[padding_idx] = 0.
    
        return torch.FloatTensor(sinusoid_table)
    

    实践经验

    在分类任务中,与BILSTM+ATTENTION链接)相比:

    1. 模型比LSTM大很多,同样的任务LSTM模型6M左右,Transformer模型55M;
    2. 收敛速度比较慢;
    3. 超参比较多,不易调参,但同时也意味着弹性比较大;
    4. 效果和BILSTM模型差不多;

    相关文章

    • 使用TextCNN模型进行文本分类(链接);
    • 使用BILSTM+ATTENTION模型进行文本分类(链接
    展开全文
  • Transformer原理以及文本分类实战

    千次阅读 2020-06-01 16:41:45
    目录1. Model2. Encoder2.1 Position encoding2.2 ...Transformer通过大量使用Attention代替了Seq2seq中的RNN结构,使得整个模型可以并行计算(RNN只能等待t-1时间步计算完成才能计算下一个时间步t)。 正如所有的Seq2

    1. Model

    在此之前,假定你已经了解了:RNN(LSTM),Sequence2Sequence模型以及注意力机制。Transformer通过大量使用Attention代替了Seq2seq中的RNN结构,使得整个模型可以并行计算(RNN只能等待t-1时间步计算完成才能计算下一个时间步t)。
    正如所有的Seq2seq一样,整个模型也分为Encoder以及Decoder两部分(分别对应图中的左边和右边)。
    在这里插入图片描述
    Encoder在给定一个sequence(x1…xn)的输入之后,将其映射到隐藏层H(h1…hn);Decoder以H为输入,一次一个字符地生成解码之后的结果(y1…ym),这里n不一定等于m。为了告知Decoder开始与结束,最初的输入是一个表示开始的特殊字符(这里假定是< START>),直到输出< END>为止。对于文本分类等下游任务,只需要用到Encoder部分即可。Bert也只用到了Encoder,因此我们把重点放在Encoder上。

    2. Encoder

    Encoder部分使用了Nx=6个相同的Block,每个Block可以拆解为如下四个部分:
    在这里插入图片描述
    最开始的Inputs是我们经常能见到的三维张量:batch×sequence_length×embedding_dim。输出X_hidden和输入差不多。

    2.1 Position encoding

    因为Transformer没有RNN中的顺序结构,因此需要加入单词的位置信息来显示地表明单词上下文关系。论文中使用了下面的式子来进行位置嵌入:
    在这里插入图片描述
    其中PE是一个二维矩阵,形状就是sequence_length×embedding_dim,pos是单词在句子中的位置,d_model表示词嵌入的维度,i表示词向量的位置。奇数位置使用cos,偶数位置使用sin。这样就根据不同的pos以及i便可以得到不同的位置嵌入信息,然后,PE同对应单词的embedding相加,输入给第二层。我们通过可视化的方式来验证这两个函数为什么能产生不同的位置信息:

    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns
    import math
    
    def get_position_encoding(seq_len, embed):
        pe = np.array([[pos / (10000.0 ** (i // 2 * 2.0 / embed)) for i in range(embed)] for pos in range(seq_len)])  # 公式实现
        pe[:, 0::2] = np.sin(pe[:, 0::2])
        pe[:, 1::2] = np.cos(pe[:, 1::2])
        return pe
    pe = get_position_encoding(100,100)
    sns.heatmap(pe)
    plt.xlabel('emb')
    plt.ylabel('seq_len')
    plt.show()
    

    下面生成的heat map很好地展示了函数的周期性。每一行都对应了一个position encoding,并且随着行列的增加,其变化的周期都在逐渐增加。因此每一个POS和i产生的位置信息都是不同的。
    在这里插入图片描述

    2.2 Multi-Head Attention

    这部分的详解可以参见一个知乎的帖子:https://zhuanlan.zhihu.com/p/47282410。attention函数可以看作将一个query和一系列key-value对映射为一个输出(output)的过程。
    在这里插入图片描述
    self-attention的具体结构如左图所示,首先,通过对初始输入X做三种不同的线性变换我们得到大家耳熟能详的KQV:Q = WQ X ; K = WK X ; V= WV X。
    之后,通过scaled Dot-Production得到输出,其中dk是词向量的维度,除以dk1/2 的这个操作也就是所谓的scaled。这个操作是为了使softmax之后的结果变得更稳定。Q与KT的结果是一个n×n的矩阵,表示这句话中每个单词对于其它任意单词的注意力。然后再乘V(初始输入X变换之后的特征值),就得到了注意力加权之后的特征,这个特征相比于X,维度并没有任何变化。
    在这里插入图片描述
    Mask的作用是在计算softmax的时候对padding的部分进行屏蔽,避免了这部分无用信息对后面的影响。
    接下来就是论文中的核心Multi-Head Attention部分了。Multi-Head Attention就是把上述的过程的过程做H次,然后把输出拼接起来。论文中采用了对KQV进行分割的方式实现多头注意力,也就是把shape为batch×sequence_length×embedding_dim的三个张量reshape成【batch×sequence_length×head×embedding_dim//head】,因此在代码实现的过程中也必须要注意head数必须能够被词嵌入的维度整除
    公式描述如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    Add&Norm

    Add表示残差连接,为了防止模型过深带来的梯度消失或梯度爆炸问题。
    在这里插入图片描述
    norm则表示Layer Normalization。

    Feed forward

    两次线性变换之后并经过relu激活函数,之后重复Add&Norm之中的操作。
    在这里插入图片描述

    3. Decoder

    同Encoder一样,Decoder也有6层,只不过在最开始多了一个Mask的多头注意力,这个确保了pos位置的预测结果只能取决于pos之前的预测结果。

    4. 源码解读(pytorch)

    由于只关注文本分类任务,所以代码中只包含Encoder的实现。代码借鉴了github上的一位大佬,https://github.com/649453932/Chinese-Text-Classification-Pytorch/blob/master/models/Transformer.py
    我们先规定输入的三维张量为x。
    然后,我们去实现上边的提到的部件。第一个是Positional_Encoding。

    class Positional_Encoding(nn.Module):
    	'''
    	params: embed-->word embedding dim      pad_size-->max_sequence_lenght
    	Input: x
    	Output: x + position_encoder
    	'''
        def __init__(self, embed, pad_size, dropout):
            super(Positional_Encoding, self).__init__()
            self.pe = torch.tensor([[pos / (10000.0 ** (i // 2 * 2.0 / embed)) for i in range(embed)] for pos in range(pad_size)])
            self.pe[:, 0::2] = np.sin(self.pe[:, 0::2])   # 偶数sin
            self.pe[:, 1::2] = np.cos(self.pe[:, 1::2])   # 奇数cos
            self.dropout = nn.Dropout(dropout)
    
        def forward(self, x):
        	# 单词embedding与位置编码相加,这两个张量的shape一致
            out = x + nn.Parameter(self.pe, requires_grad=False).cuda()
            out = self.dropout(out)
            return out
    

    Multi-Head Attention

    class Multi_Head_Attention(nn.Module):
    	'''
    	params: dim_model-->hidden dim      num_head
    	'''
        def __init__(self, dim_model, num_head, dropout=0.0):
            super(Multi_Head_Attention, self).__init__()
            self.num_head = num_head
            assert dim_model % num_head == 0    # head数必须能够整除隐层大小
            self.dim_head = dim_model // self.num_head   # 按照head数量进行张量均分
            self.fc_Q = nn.Linear(dim_model, num_head * self.dim_head)  # Q,通过Linear实现张量之间的乘法,等同手动定义参数W与之相乘
            self.fc_K = nn.Linear(dim_model, num_head * self.dim_head)
            self.fc_V = nn.Linear(dim_model, num_head * self.dim_head)
            self.attention = Scaled_Dot_Product_Attention() 
            self.fc = nn.Linear(num_head * self.dim_head, dim_model)
            self.dropout = nn.Dropout(dropout)
            self.layer_norm = nn.LayerNorm(dim_model)   # 自带的LayerNorm方法
    
        def forward(self, x):
            batch_size = x.size(0)
            Q = self.fc_Q(x)
            K = self.fc_K(x)
            V = self.fc_V(x)
            Q = Q.view(batch_size * self.num_head, -1, self.dim_head)  # reshape to batch*head*sequence_length*(embedding_dim//head)
            K = K.view(batch_size * self.num_head, -1, self.dim_head)
            V = V.view(batch_size * self.num_head, -1, self.dim_head)
            # if mask:  # TODO
            #     mask = mask.repeat(self.num_head, 1, 1)  # TODO change this
            scale = K.size(-1) ** -0.5  # 根号dk分之一,对应Scaled操作
            context = self.attention(Q, K, V, scale) # Scaled_Dot_Product_Attention计算
            context = context.view(batch_size, -1, self.dim_head * self.num_head) # reshape 回原来的形状
            out = self.fc(context)   # 全连接
            out = self.dropout(out)
            out = out + x      # 残差连接,ADD
            out = self.layer_norm(out)  # 对应Norm
            return out
    

    scaled Dot-Production

    class Scaled_Dot_Product_Attention(nn.Module):
        '''Scaled Dot-Product'''
        def __init__(self):
            super(Scaled_Dot_Product_Attention, self).__init__()
    
        def forward(self, Q, K, V, scale=None):
            attention = torch.matmul(Q, K.permute(0, 2, 1))  # Q*K^T
            if scale:
                attention = attention * scale
            # if mask:  # TODO change this
            #     attention = attention.masked_fill_(mask == 0, -1e9)
            attention = F.softmax(attention, dim=-1)
            context = torch.matmul(attention, V)   
            return context
    

    最后一个部件是Feed Forward

    class Position_wise_Feed_Forward(nn.Module):
        def __init__(self, dim_model, hidden, dropout=0.0):
            super(Position_wise_Feed_Forward, self).__init__()
            self.fc1 = nn.Linear(dim_model, hidden)
            self.fc2 = nn.Linear(hidden, dim_model)
            self.dropout = nn.Dropout(dropout)
            self.layer_norm = nn.LayerNorm(dim_model)
    
        def forward(self, x):
            out = self.fc1(x)
            out = F.relu(out)
            out = self.fc2(out)   # 两层全连接
            out = self.dropout(out)
            out = out + x  # 残差连接
            out = self.layer_norm(out)
            return out
    

    然后看整体的Encoder实现:

    class Encoder(nn.Module):
        def __init__(self, dim_model, num_head, hidden, dropout):
            super(Encoder, self).__init__()
            self.attention = Multi_Head_Attention(dim_model, num_head, dropout)
            self.feed_forward = Position_wise_Feed_Forward(dim_model, hidden, dropout)
    
        def forward(self, x):
            out = self.attention(x)
            out = self.feed_forward(out)
            return out
    

    5. 文本分类实战

    本文分类使用公开数据集mr,按照默认的方式拆分训练集与测试集。使用Stanford的Glove50将数据处理成上文提到的张量格式,对于不同的Sequence需要补全成相同的长度。
    对于其它参数,配置如下:

    class ConfigTrans(object):
    
        """配置参数"""
        def __init__(self):
            self.model_name = 'Transformer'
            self.dropout = 0.5                              
            self.num_classes = cfg.classes                      # 类别数
            self.num_epochs = 100                # epoch数
            self.batch_size = 128             # mini-batch大小
            self.pad_size = cfg.nV                     # 每句话处理成的长度(短填长切),这个根据自己的数据集而定
            self.learning_rate = 0.001                    # 学习率
            self.embed = 50          # 字向量维度
            self.dim_model = 50      # 需要与embed一样
            self.hidden = 1024 
            self.last_hidden = 512
            self.num_head = 5       # 多头注意力,注意需要整除
            self.num_encoder = 2    # 使用两个Encoder,尝试6个encoder发现存在过拟合,毕竟数据集量比较少(10000左右),可能性能还是比不过LSTM
    config = ConfigTrans()
    
    class Transformer(nn.Module):
        def __init__(self):
            super(Transformer, self).__init__()
            self.postion_embedding = Positional_Encoding(config.embed, config.pad_size, config.dropout)
            self.encoder = Encoder(config.dim_model, config.num_head, config.hidden, config.dropout)
            self.encoders = nn.ModuleList([
                copy.deepcopy(self.encoder)
                for _ in range(config.num_encoder)])   # 多次Encoder
    
            self.fc1 = nn.Linear(config.pad_size * config.dim_model, config.num_classes)
    
        def forward(self, x):
            out = self.postion_embedding(x)
            for encoder in self.encoders:
                out = encoder(out)
            out = out.view(out.size(0), -1)  # 将三维张量reshape成二维,然后直接通过全连接层将高维数据映射为classes
            # out = torch.mean(out, 1)    # 也可用池化来做,但是效果并不是很好
            out = self.fc1(out)
            return out
    

    结果分析:
    在epoch=40设置learning rate decay,decay rate 0.97,并将early stop设置为20,损失函数使用pytorch自带的交叉熵。在epoch=51时early stop,mr准确率约为71%。对比BiLSTM+Attention的73.86%,准确率反而逊色。可能是因为transformer更适用于较大的数据集,mr的数据量还是比较小。

    Epoch:51---------loss:34.51407927274704-----------time:8.6797354221344
    epoch:51 	 test_acc:0.7062464828362408	best_acc:0.7121553179516038
    early stop!!! Best acc:0.7121553179516038
    

    参考

    https://www.bilibili.com/video/BV1sE411Y7cP?from=search&seid=2004285655536337633
    https://www.jianshu.com/p/0c196df57323
    https://blog.csdn.net/qq_29695701/article/details/88096455

    展开全文
  • Transformer引入视觉领域后,研究人员们一直在寻求更好的模型架构来适应视觉领域的通用任务。但将Transformer从NLP领域迁移到CV领域面临着众多挑战,与文本相比图像中的视...

    将Transformer引入视觉领域后,研究人员们一直在寻求更好的模型架构来适应视觉领域的通用任务。但将Transformer从NLP领域迁移到CV领域面临着众多挑战,与文本相比图像中的视觉实体尺度变化剧烈、图像分辨率很高,带来了多尺度建模与计算量巨大的严峻问题。

    为了解决这些问题,研究人员提出了一种基于移动窗格和层级表达的通用架构。移动窗口将自注意力限制在一定范围内大幅度削减了计算量,同时也使得非局域窗口间的交互成为可能。

    这一灵活架构适用于多种视觉任务并具有 (与图像大小的) 线性复杂度。实验表明这一架构在图像分类、目标检测和图像分割等多个任务上达到了目前的最领先水平,显示出了其作为视觉任务基础模型的强大潜力。

    论文链接:

    https://arxiv.org/abs/2103.14030

    项目网站:

    https://github.com/microsoft/Swin-Transformer


    从CNNs迈向Transformer

    自从AlexNet在ImageNet上取得重大突破后,CNNs便主导着各个视觉领域的研究,从架构规模、卷积结构等方向持续演进,在深度学习的发展历史中大放异彩,作为基础网络为各式各样的视觉任务提供了强有力的特征抽取和表达,极大地促进了整个视觉领域的繁荣发展。

    另一方面在自然语言处理领域也诞生了以Transformer为代表的序列模型架构,利用attention机制为数据的长程依赖性建模大幅度提升了语言模型的性能。在自然语言领域取得的巨大成功让科学家们开始探索Transformer在计算机视觉领域应用的可能性,最近的研究展示了广阔的应用前景。

    拓展Transformer的实用性、使其成为通用的视觉架构是本研究的努力方向。Transformer在视觉领域的应用挑战相比于自然语言处理主要体现在两方面。

    其一是图像领域的实体尺度变化剧烈在目标检测任务中尤其如此,而现有transformer架构固定的token尺度无法适应如此大范围变化的目标尺寸;

    其二是图像的像素分辨率远远高于文本中的单词,像语义分割这样涉及像素级稠密预测的视觉任务,Transformer中自注意力机制会带来非常庞大的计算(像素数的平方复杂度)。

    为了克服这些问题,研究人员提出了一种新的视觉Transformer架构Swin Transformer,在线性计算复杂度的基础上构建了图像的层级特征图。下图展示了Swin Transformer架构以及与ViT的基本区别。其中Swin Transformer通过小图像片元和逐层进行邻域合并的方式构建层级特征表达,这样的架构使得模型可以实现与U-Net和FPN等架构类似的稠密预测任务。

    而这一高效模型的线性计算复杂度则由图中非重叠窗口内的局域自注意力机制实现,由于每层窗口中的片元固定,所以与图像大小具有线性复杂度关系。而ViT中的特征图大小是固定的,且需要进行(对图像大小)二次复杂度的计算。

    Swin Transformer和ViT的架构区别

    Swin Transformer最为关键的设计在于连续自注意力层间,特征图上的窗划分口实现了半个窗宽的移动。这使得前一层的窗口间可以实现交互和联系,大幅度提升了模型的表达能力。同时在同一窗口内的查询都拥有相同的key序列,使得硬件内存更容易实现大大提升了模型运行的速度,降低延时。

    这一架构在多种视觉任务上都实现了最先进的性能,也再一次展示了CV和NLP领域的相互促进,和视觉与-文本信号的融合建模的广阔前景,并为统一框架的提出打下了坚实的基础。下面就让我们一起来分析Swin Transformer的详细结构与实现吧。

    Swin Transformer

    Swin Transformer以原始图像片元像素作为输入,通过编码后得到像素的特征而后逐级传递最终获取图像的特征表达。在本研究中使用了4x4的片元作为输入,每个片元作为一个token,输入的维度为W/4xH/4x48,而后通过一次线性变换得到了W/4xH/4xC的特征表达。

    通过本文提出的Swin Transformer block单元对输入特征进行计算。后续的层一方面将相邻的2x2片元特征进行衔接融合得到4C维度的特征,并输入2C的融合特征,而另一方面,在水平方向上图像分辨率也变成了W/8xH/8,最终生成了W/8xH/8x4C的特征。

    以此类推,随着blcok的叠加,特征的维度依次变成了W/16xH/16x8C和W/32xH/32x16C,与VGG和ResNet等典型卷积模型的特征图分辨率一致,使其可便捷的成为相关模型的基础架构。

     Swin Transformer的基础架构示意图

    Swin Transformer中最重要的模块是基于移动窗口构建的注意力模块,其内部结构如下图所示,包含了一个基于移动窗口的多头自注意力模块(shifted windows multi-head self attention, SW-MSA)和基于窗口的多头自注意力模块(W-MSA),其他的归一化层和两层的MLP与原来保持一致,并使用了GELU激活函数。

    基于移动窗口的W-MSA和基于窗口的SW-MSA模块前后相连,实现不同窗格内特征的传递与交互

    基于移动窗口的自注意力模块是本研究的关键所在,下面将详细介绍这一部分的原理和实现方法。

    基于移动窗口的自注意力模块

    标准的全局自注意机制需要计算每一个token和其他所有token的相关性,全局计算带来了与token数量二次方的复杂度。这一机制的计算量对于具有大量像素的稠密视觉预测任务十分庞大,很多时候巨大的计算量对于目前的硬件来说不易实现。


    为了高效的实现这一模型,研究人员提出仅仅在局域窗口内进行自注意力计算,而窗口则来自于对图像的非重叠均匀划分。假设每个窗口中包含M x M个片元,整张图像共包含h x w个片元,那么标准的和基于窗口的全局注意力模块的计算复杂度如下:

    可以看到标准的全局注意力计算方式与片元数量的二次关系带来了庞大的计算量,而基于窗格的方式由于M固定则仅仅成线性关系,使得高效计算成为可能。

    但这种基于窗格的方式缺乏窗格间的交互,限制了模型的表达能力。为了实现窗格间的交互,研究人员提出了一种在连续特征层间移动窗口的方式来实现。这种机制中,第一个特征图窗格按照正常的方式将8x8的特征图分割为了4x4个窗格(M=4)。而后在下一层中将窗格整体移动(M/2,M/2),以此来实现窗格间的交互。

    其中z为第l层的输出特征,W-MSA和SW-MSA分别代表了基于窗格的多头注意力机制和基于移动窗格的多头注意力机制。下图中展示了窗格移动带来的信息交互,前一层中不同窗格间的信息在下一层中被有效的链接在了一起。原来四个独立的窗格内的特征图在移动后都被部分分入新的窗格,从而实现了更为复杂的交互机制。

    基于移动窗格的自注意力机制计算

    虽然这种方式可以有效实现窗格间的交互和全局注意力,但却会带来窗格数量增加的问题。在移动后所有的窗格数量增加到了9个会带来相应计算量的提升。

    一种简单方法的是将外围的小窗格都padding成与原来MxM大小,但这会带来(3x3)/(2x2)=2.25倍的计算量提升。为此研究人员提出了更为高效的解决方案,利用像左上角的循环移位操作(cyclic-shifting)来实现。

    基于circle shift的移动窗格计算

    此时9个窗格通过循环移位后由重新变回了4个窗格,保持了计算量的一致。此时每个窗格中包含了来自原来不同窗格中的特征图,此时要计算自注意力则需要引入一定的mask机制将不同窗格子窗格中的计算去除掉,仅仅计算同一个子窗格中的自注意力。实验表明这个机制使得模型的延时大大降低

    网络架构和实验结果

    为了比较不同的模型容量及其性能,研究人员分别实现了Swin-Tiny、Swin-Small、Swin-Base、Swin-Large四种不同的模型,其配置主要区别在于C的维度和每个stage的层数上。

    实验分别在图像分类ImageNet-1K、目标检测COCO、和语义分割ADE20K数据集上进行。下面的表格展示了Swin Transformer的强大能力。

    首先在图像分类任务中,可以看到这一架构大幅超越了先前基于transformer的DeiT架构,与最先进的卷积模型相比也实现了速度与精度的平衡。值得注意的是下表中的卷积模型来自于架构搜索,而这里使用的基础型Swin-Base则还有很大的提升空间。

    同样在目标检测任务中,本文提出的架构不仅超过了DeiT,同时也大幅优于各种基于卷积的先进架构。在COCO test-dev上实现了58.7 box AP 和 51.1 mask AP,分别超过了先前最好模型2.7和2.6个点。

    最后在语义分割任务上,这一模型在ADE20k上比先前最好的SETR模型高出了3.2的mIoU,实现了最先进的性能。

    如果想要了解更多细节和实验原理,请参考论文和项目网站。

    编译: T.R From: MSRA

    Illustrastion by Oleg Shcherba from Icons8

    备注:综合

    计算机视觉交流群

    图像分割、姿态估计、智能驾驶、超分辨率、自监督、无监督、2D、3D目标检测等最新资讯,若已为CV君其他账号好友请直接私信。

    展开全文
  • 最近, Swin Transformer成为...本文主要介绍在MMCls中使用Swin-Transformer开始一个分类任务,具体代码下载:谷歌网盘。 相关教程文档:欢迎来到 MMClassification 中文教程! — MMClassification 0.16.0 文档..
  • 点上方人工智能算法与Python大数据获取更多干货在右上方···设为星标★,第一时间获取资源仅做学术分享,如有侵权,联系删除转载于 :机器之心在如今的 NLP 领域,几乎每项任务中都...
  • 第一个是手工进行的特征提取和分类,第二个使用深度神经网络。 在我们的论文中,我们还提出了用于年龄估计的视觉转换器。 它是最早提出用于面部任务的视觉转换器之一,因此没有预训练的模型。 但是,我们仍然设法在...
  • Swin-Transformer分类源码(已跑通)

    千次阅读 多人点赞 2021-05-19 07:55:32
    1、Swin-Transformer分割源码(已跑通) 2、关于swin transformer原理的一些补充理解 3、Swin-Unet(分割改编) 一. 概要 最近swin-transformer大火,代码开源两天,girhub直接飙到1.9k。估计接下来关于和swin-...
  • 【解析】Vision Transformer 在图像分类中的应用

    千次阅读 多人点赞 2021-04-10 22:52:29
    这个工作本着尽可能少修改的原则,将原版的Transformer开箱即用地迁移到分类任务上面。并且作者认为没有必要总是依赖于CNN,只用Transformer也能够在分类任务中表现很好,尤其是在使用大规模训练集的时候。同时,在...
  • Swin变形金刚-PyTorch ... Swin Transformer的这些品质使其可与多种视觉任务兼容,包括图像分类(ImageNet-1K的准确度为86.4 top-1)和密集的预测任务,例如目标检测(COCO测试中为58.7框式AP和51.1遮罩式
  • 分类 图像价值16x16字:用于图像识别的变压器[VIT] [ICLR 2021] [] [] DeiT:数据高效的图像变压器[arxiv2021] [] [] 侦测 DETR:使用变压器进行端到端对象检测[ECCV2020] [] [] 可变形DETR:用于端到端对象检测的...
  • Transformer 是基于注意力的神经网络,旨在解决 NLP 任务。 它们的主要特点是: 特征向量维度的线性复杂度; 序列计算的并行化,而不是顺序计算; 长期记忆,因为我们可以直接查看任何输入时间序列步骤。 这个 ...
  • 使用transformer进行图像分类

    千次阅读 2021-08-16 00:41:06
    文章将图像切割成一个个图像块,组成序列化的数据输入Transformer执行图像分类任务。当对大量数据进行预训练并将其传输到多个中型或小型图像识别数据集(如ImageNet、CIFAR-100、VTAB等)时,与目前的卷积网络相比,...
  • 作为一种self-attention架构,transformer的主要方法是在一个较大文本语料库进行预训练,然后在一个小的特定任务数据集上进行微调。但是实验表明,在大尺寸架构如ResNet上训练后再迁移至中等尺寸数据集,分类正确率...
  • LeViT: a Vision Transformer in ConvNet’s Clothing for Faster Inference 论文:https://arxiv.org/pdf/2104.01136.pdf 代码:https://github.com/facebookresearch/LeViT 摘要 我们提出了LeVIT:一种用于快速...
  • hugging face transformer文本分类运行

    千次阅读 2020-01-08 17:59:58
    hugging face 团队的transformer又更新了,现在里面有distilroberta和distilbert和albert模型,这三个模型值得我们对比其他模型的差异。那么如何运行呢? 首先进入GitHub,搜索transformer ... 进入这个repo ...
  • Transformer在细粒度分类上的应用

    千次阅读 2021-03-25 21:18:53
    TransFG :Transformer在细粒度分类上的应用一级目录二级目录三级目录 一级目录 二级目录 三级目录
  • 6. 文本分类——transformer模型

    千次阅读 2020-03-22 20:43:56
    文章目录一、简介二、transformer结构三、用于文本分类transformer1. embedding layer(嵌入层)2. positional encoding(位置编码)3. Scaled dot-product attention(缩放的点乘注意力机制)4. Multi-head ...
  • 文章将图像切割成一个个图像块,组成序列化的数据输入Transformer执行图像分类任务。当对大量数据进行预训练并将其传输到多个中型或小型图像识别数据集(如ImageNet、CIFAR-100、VTAB等)时,与目前的卷积网络相比,...
  • 用Pytorch实现Transformer

    2019-04-04 18:12:44
    用Python实现Transformer,How to code The Transformer in Pytorch ,Samuel Lynn‑Evans。
  • 【亲测】Swin-Transformer 自定义数据集图像分类

    千次阅读 热门讨论 2021-10-20 12:10:47
    Swin-Transformer是当前热门的深度学习框架,适用于多种视觉任务,相关的原理,网上有很多资源,大家可自行查看,这里主要介绍其在图像分类方面的代码调试经验,方便各位快速上手实验。Swin-Transformer代码链接点击...
  • 【深度学习】U型的Transfomer网络(Swin-Unet)和Swin-Transformer分类 文章目录 1 概述 2 Swin-Transformer分类源码 3 训练 4 关于复杂度降低问题 5 关于SW-MSA的操作问题 6 总结 1 概述 代码暂时还未开源。 在...
  • 实验与总结 本文提出的多模态预训练模型各个板块划分明确,通过多层Transformer分别提取特征,再利用解码器机制融合特征并完成下游任务,同时借助最后一层任务相关的处理器,可以通过一个模型解决多个任务,同时也...
  • 本文首先将简要介绍Transformer的原理与其各个组成部分、...接下来文章从图片分类与目标检测的角度介绍相应Transformer的应用;最后本文将介绍Transformer在应用到CV领域时依然存在的不足以及未来可能的研究方向。
  • transformer在图像分类上的应用以及pytorch代码实现

    万次阅读 多人点赞 2021-04-09 12:54:58
    对transformers的简单介绍1.1序列数据的介绍(seq2seq)1.2self-Attention1.3 transformer的完整结构2.transformers在图像分类上的pytorch代码2.1加载cifar10数据集2.2构建transformers模型2.2.1构建图像编码模块 ...
  • 在一些计算机视觉的基准任务中,基于Transformer的模型取得了与CNN或RNN网络等相近甚至更优越的性能。鉴于其优越的性能,同时无需过多的输入所需的先验知识,Transformer越来越多的被用于计算机视觉领域。 本文对...
  • 当前,它包含用于以下任务的代码和模型: 图像分类:包含在此仓库中。 有关快速,请参见 。 对象检测和实例分割:有关对象检测,请参见 。 语义分割:有关语义分割的信息,请参见 。 更新 2021年4月12日 初始...
  • Transformer 在多个模态(语言、图像、蛋白质序列)中获得了 SOTA 结果,但它存在一个缺点:自注意力机制的平方级复杂度限制了其在长序列领域中的应用。目前,研究人员提出大量高效 Transformer 模型(「xformer」)...
  • 介绍Transformer的发明最近取代了自然语言处理的世界。transformers是完全无视传统的基于序列的网络。RNN是用于基于序列的任务(如文本生成,文本分类等)的最初武器。但是,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,218
精华内容 5,287
关键字:

transformer分类任务

友情链接: PIC-examples-16-20.zip