第三课:GPT

news2024/11/26 14:35:08

文章目录

  • 第三课:GPT
    • 1、学习总结:
      • GPT出现的原因
      • GPT的方法原理
      • 目前存在的问题
      • 无监督的预训练
        • 优化目标
        • 模型结构
      • 监督微调
      • 课程ppt及代码地址
    • 2、学习心得:
    • 3、经验分享:
    • 4、课程反馈:
    • 5、使用MindSpore昇思的体验和反馈:
    • 6、未来展望:

第三课:GPT

1、学习总结:

GPT出现的原因

未标注的文本数据远多于已标注的文本数据,并且对于不同的下游任务会存在不同的标注方式

GPT的方法原理

半监督学习

  • 基于大量未标注的文本数据,训练预训练语言模型
  • 使用已标注文本数据,对模型针对某一特定下游任务进行finetune,只更改output layer(线性层)

目前存在的问题

  • 自然语言处理的下游任务非常多元,难以有统一的优化目标
  • 难以将预训练模型的信息完全传递到finetune的下游任务中

无监督的预训练

优化目标

模型结构

由于训练objective的选择,gpt在模型选择上不应该看见当前token后的信息,故模型应设计为单向网络,即transformer中的decoder结构。

image-20240120215223634

import os
import logging
import numpy as np
import mindspore
from mindspore import nn
from mindspore import ops
from mindspore import Tensor
from mindspore.common.initializer import initializer, Normal
from mindnlp.models.gpt.gpt_config import GPTConfig
from mindnlp._legacy.nn import Dropout
from mindnlp.abc import PreTrainedModel
from mindnlp.models.utils import Conv1D, prune_conv1d_layer, find_pruneable_heads_and_indices
from mindnlp.models.utils import SequenceSummary
from mindnlp.models.activations import ACT2FN
from mindnlp import GPTConfig
# Feed-Forward 实现
class MLP(nn.Cell):
    r"""
    GPT MLP
	"""

    def __init__(self, n_state, config):
        super().__init__()
        n_embd = config.n_embd
        self.c_fc = Conv1D(n_state, n_embd)
        self.c_proj = Conv1D(n_embd, n_state)
        self.act = ACT2FN[config.afn]
        self.dropout = Dropout(p=config.resid_pdrop)

    def construct(self, x):
        h = self.act(self.c_fc(x))
        h2 = self.c_proj(h)
        return self.dropout(h2)
# Multi-head attention 实现

class Attention(nn.Cell):
    r"""
    GPT Attention
    """

    def __init__(self, nx, n_positions, config, scale=False):
        super().__init__()
        n_state = nx
        if n_state % config.n_head != 0:
            raise ValueError(f"Attention n_state shape: {n_state} must be divisible by config.n_head {config.n_head}")

        self.bias = Tensor(np.tril(np.ones((n_positions, n_positions))), mindspore.float32).view(1, 1, n_positions, n_positions)
        self.n_head = config.n_head
        self.split_size = n_state
        self.scale = scale

        self.c_attn = Conv1D(n_state * 3, n_state)
        self.c_attn = Conv1D(n_state * 3, n_state)
        self.c_proj = Conv1D(n_state, n_state)
        self.attn_dropout = Dropout(p=config.attn_pdrop)
        self.resid_dropout = Dropout(p=config.resid_pdrop)
        self.pruned_heads = set()

        self.output_attentions = config.output_attentions

    def prune_heads(self, heads):
        """
        Prunes heads of the model.
        """
        if len(heads) == 0:
            return
        head_size = self.split_size//self.n_head
        heads, index = find_pruneable_heads_and_indices(heads, self.n_head, head_size, self.pruned_heads)
        index_attn = ops.cat([index, index + self.split_size, index + (2 * self.split_size)])
        self.c_attn = prune_conv1d_layer(self.c_attn, index_attn, axis=1)
        self.c_proj = prune_conv1d_layer(self.c_proj, index, axis=0)
        self.split_size = (self.split_size // self.n_head) * (self.n_head - len(heads))
        self.n_head = self.n_head - len(heads)
        self.pruned_heads = self.pruned_heads.union(heads)

    def _attn(self, q, k, v, attention_mask=None, head_mask=None):
        w = ops.matmul(q, k)
        if self.scale:
            w = w / ops.sqrt(ops.scalar_to_tensor(v.shape[-1]))
        b = self.bias[:, :, : w.shape[-2], : w.shape[-1]]
        w = w * b + -1e9 * (1 - b)

        if attention_mask is not None:
            w = w + attention_mask

        w = ops.softmax(w)
        w = self.attn_dropout(w)

        if head_mask is not None:
            w = w * head_mask

        outputs = (ops.matmul(w, v),)
        if self.output_attentions:
            outputs += (w,)
        return outputs


    def merge_heads(self, x):
        """merge heads"""
        x = x.transpose(0, 2, 1, 3)
        new_x_shape = x.shape[:-2] + (x.shape[-2] * x.shape[-1],)
        return x.view(new_x_shape)

    def split_heads(self, x, k=False):
        """split heads"""
        new_x_shape = x.shape[:-1] + (self.n_head, x.shape[-1] // self.n_head)
        x = x.view(new_x_shape)
        if k:
            return x.transpose(0, 2, 3, 1)
        return x.transpose(0, 2, 1, 3)

    def construct(self, x, attention_mask=None, head_mask=None):
        x = self.c_attn(x)
        query, key, value = ops.split(x, self.split_size, axis=2)
        query = self.split_heads(query)
        key = self.split_heads(key, k=True)
        value = self.split_heads(value)

        attn_outputs = self._attn(query, key, value, attention_mask, head_mask)
        a = attn_outputs[0]

        a = self.merge_heads(a)
        a = self.c_proj(a)
        a = self.resid_dropout(a)
        outputs = (a,) + attn_outputs[1:]
        return outputs
class Block(nn.Cell):
    r"""
    GPT Block
    """

    def __init__(self, n_positions, config, scale=False):
        super().__init__()
        nx = config.n_embd
        self.attn = Attention(nx, n_positions, config, scale)
        self.ln_1 = nn.LayerNorm((nx,), epsilon=config.layer_norm_epsilon)
        self.mlp = MLP(4 * nx, config)
        self.ln_2 = nn.LayerNorm((nx,), epsilon=config.layer_norm_epsilon)

    def construct(self, x, attention_mask=None, head_mask=None):
        output_attn = self.attn(
            x,
            attention_mask=attention_mask,
            head_mask=head_mask
        )

        a = output_attn[0]
        n = self.ln_1(x + a)
        m = self.mlp(n)
        h = self.ln_2(n + m)

        outputs = (h,) + output_attn[1:]
        return outputs
class GPTPreTrainedModel(PreTrainedModel):
    """BertPretrainedModel"""
    convert_torch_to_mindspore = torch_to_mindspore
    pretrained_model_archive_map = PRETRAINED_MODEL_ARCHIVE_MAP
    config_class = GPTConfig
    base_model_prefix = 'transformer'

    def _init_weights(self, cell):
        """Initialize the weights"""
        if isinstance(cell, nn.Dense):
            cell.weight.set_data(initializer(Normal(self.config.initializer_range),
                                                    cell.weight.shape, cell.weight.dtype))
            if cell.has_bias:
                cell.bias.set_data(initializer('zeros', cell.bias.shape, cell.bias.dtype))
        elif isinstance(cell, nn.Embedding):
            embedding_table = initializer(Normal(self.config.initializer_range),
                                                 cell.embedding_table.shape,
                                                 cell.embedding_table.dtype)
            if cell.padding_idx is not None:
                embedding_table[cell.padding_idx] = 0
            cell.embedding_table.set_data(embedding_table)
        elif isinstance(cell, nn.LayerNorm):
            cell.gamma.set_data(initializer('ones', cell.gamma.shape, cell.gamma.dtype))
            cell.beta.set_data(initializer('zeros', cell.beta.shape, cell.beta.dtype))

class GPTModel(GPTPreTrainedModel):
    """
    The bare GPT transformer model outputting raw hidden-states without any specific head on top
    """

    def __init__(self, config):
        super().__init__(config)
        self.config = config
        self.tokens_embed = nn.Embedding(config.vocab_size, config.n_embd)
        self.positions_embed = nn.Embedding(config.n_positions, config.n_embd)
        self.drop = nn.Dropout(p=config.embd_pdrop)
        self.h = nn.CellList([Block(config.n_positions, config, scale=True) for _ in range(config.n_layer)])
        self.position_ids = ops.arange(config.n_positions)

        self.n_layer = self.config.n_layer
        self.output_attentions = self.config.output_attentions
        self.output_hidden_states = self.config.output_hidden_states

    def get_input_embeddings(self):
        """
        return the input embeddings layer
        """
        return self.tokens_embed

    def set_input_embeddings(self, value):
        """
        set the input embeddings layer
        """
        self.tokens_embed = value

    def _prune_heads(self, heads_to_prune):
        """
        Prunes heads of the model. heads_to_prune: dict of {layer_num: list of heads to prune in this layer}
        """
        for layer, heads in heads_to_prune.items():
            self.h[layer].attn.prune_heads(heads)

    def construct(
            self,
            input_ids=None,
            attention_mask=None,
            token_type_ids=None,
            position_ids=None,
            head_mask=None,
            inputs_embeds=None,
    ):
        if input_ids is not None and inputs_embeds is not None:
            raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
        if input_ids is not None:
            input_shape = input_ids.shape
            input_ids = input_ids.view(-1, input_shape[-1])
        elif inputs_embeds is not None:
            input_shape = inputs_embeds.shape[:-1]
        else:
            raise ValueError("You have to specify either input_ids or inputs_embeds")

        if position_ids is None:
            position_ids = self.position_ids[None, : input_shape[-1]]

        if attention_mask is not None:
            attention_mask = attention_mask.unsqueeze(1).unsqueeze(2)
            attention_mask = attention_mask.to(dtype=next(self.parameters()).dtype)
            attention_mask = (1.0 - attention_mask) * Tensor(np.finfo(mindspore.dtype_to_nptype(self.dtype)).min,
                                                             self.dtype)

        head_mask = self.get_head_mask(head_mask, self.n_layer)

        if inputs_embeds is None:
            inputs_embeds = self.tokens_embed(input_ids)
        position_embeds = self.positions_embed(position_ids)
        if token_type_ids is not None:
            token_type_ids = token_type_ids.view(-1, token_type_ids.shape[-1])
            token_type_embeds = self.tokens_embed(token_type_ids)
        else:
            token_type_embeds = 0
        hidden_states = inputs_embeds + position_embeds + token_type_embeds
        hidden_states = self.drop(hidden_states)

        output_shape = input_shape + (hidden_states.shape[-1],)

        all_attentions = ()
        all_hidden_states = ()
        for i, block in enumerate(self.h):
            if self.output_hidden_states:
                all_hidden_states = all_hidden_states + (hidden_states,)

            outputs = block(hidden_states, attention_mask, head_mask[i])
            hidden_states = outputs[0]
            if self.output_attentions:
                all_attentions = all_attentions + (outputs[1],)

        hidden_states = hidden_states.view(*output_shape)

        if self.output_hidden_states:
            all_hidden_states = all_hidden_states + (hidden_states,)

        return (hidden_states, all_hidden_states, all_attentions)

监督微调

在已经预训练好的GPT上额外加一层线性层

并通过缩小目标与计算结果的误差进行模型优化

最终为加速模型收敛及提高模型的泛化性,融入pretrain时language modelling的优化目标

# 文本序列分类任务

class GPTForSequenceClassification(GPTPreTrainedModel):
    """
    The Original GPT Model transformer with a sequence classification head on top (linear layer).
    GPTForSequenceClassification uses the last token in order to do the classification, as other causal
    models (e.g. GPT-2) do. Since it does classification on the last token, it requires to know the position of the
    last token. If a `pad_token_id` is defined in the configuration, it finds the last token that is not a padding
    token in each row. If no `pad_token_id` is defined, it simply takes the last value in each row of the batch. Since
    it cannot guess the padding tokens when `inputs_embeds` are passed instead of `input_ids`, it does the same (take
    the last value in each row of the batch).
    """
    def __init__(self, config):
        super().__init__(config)
        self.config = config
        self.num_labels = config.num_labels
        self.transformer = GPTModel(config)
        self.score = nn.Dense(config.n_embd, self.num_labels, has_bias=False)

        self.pad_token_id = self.config.pad_token_id
        problem_type = config.problem_type
        if problem_type is None:
            self.loss = None
        else:
            if self.num_labels == 1:
                self.problem_type = "regression"
                self.loss = nn.MSELoss()
            elif self.num_labels > 1:
                self.problem_type = "single_label_classification"
                self.loss = nn.CrossEntropyLoss()
            else:
                self.problem_type = "multi_label_classification"
                self.loss = nn.BCEWithLogitsLoss()

    def construct(
        self,
        input_ids = None,
        attention_mask = None,
        token_type_ids = None,
        position_ids = None,
        head_mask = None,
        inputs_embeds = None,
        labels = None,
    ):
        r"""
        labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
            Labels for computing the sequence classification/regression loss. Indices should be in
            `[0, ...,config.num_labels - 1]`.
            If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
            `config.num_labels > 1` a classification loss is computed (Cross-Entropy).
        """
        transformer_outputs = self.transformer(
            input_ids,
            attention_mask=attention_mask,
            token_type_ids=token_type_ids,
            position_ids=position_ids,
            head_mask=head_mask,
            inputs_embeds=inputs_embeds,
        )

        hidden_states = transformer_outputs[0]
        logits = self.score(hidden_states)

        if input_ids is not None:
            batch_size, _ = input_ids.shape[:2]
        else:
            batch_size, _ = inputs_embeds.shape[:2]

        if self.pad_token_id is None and batch_size != 1:
            raise ValueError("Cannot handle batch sizes > 1 if no padding token is defined.")

        if self.pad_token_id is None:
            sequence_lengths = -1
        else:
            if input_ids is not None:
                sequence_lengths = ops.ne(input_ids, self.pad_token_id).sum(-1) - 1
            else:
                sequence_lengths = -1

        pooled_logits = logits[:, sequence_lengths]

        loss = None

        output = (pooled_logits,) + transformer_outputs[1:]

        if labels is not None:
            if self.num_labels == 1:
                loss = self.loss(pooled_logits.squeeze(), labels.squeeze())
            elif self.num_labels > 1:
                loss = self.loss(pooled_logits.view(-1, self.num_labels), labels.view(-1))
            else:
                loss = self.loss(pooled_logits, labels)

        if loss is not None:
            output = (loss,) + output
        return output

课程ppt及代码地址

  • github地址(网络不好的可以访问下面我克隆到gitee上的地址):GPT

  • gitee地址:GPT

2、学习心得:

​ 通过本次学习,熟悉了Mindspore这个国产深度学习框架,也对GPT的基本技术原理有所了解,同时也学会了如何在IMDb数据集上微调GPT完成一个情感分类的任务,比较有成就感!!!另外就是Selina小姐姐讲课的氛围比较轻松,学起来比较快乐!

3、经验分享:

​ 在启智openI上的npu跑时记得使用mindspore1.7的镜像,同时安装对应mindnlp的版本,不然可能会因为版本不兼容而报错。另外就是IMDB情感分类任务的微调练习一定要做,这样能比较get到整个微调的全流程是怎样的,后面再去学习llama等模型的微调时就会更加得心应手。

4、课程反馈:

​ 本次课程中的代码串讲我觉得是做的最好的地方,没有照着ppt一直念,而是在jupyter lab上把代码和原理结合到一块进行讲解,让学习者对代码的理解更加深入。我觉得内容的最后可以稍微推荐一下与Mindspore大模型相关的套件,让学习者在相关套件上可以开发出更多好玩和有趣的东西!

5、使用MindSpore昇思的体验和反馈:

MindSpore昇思的优点和喜欢的方面:

  1. 灵活性和可扩展性: MindSpore提供了灵活的编程模型,支持静态计算图和动态计算图。这种设计使得它适用于多种类型的机器学习和深度学习任务,并且具有一定的可扩展性。
  2. 跨平台支持: MindSpore支持多种硬件平台,包括CPU、GPU和NPU等,这使得它具有在不同设备上运行的能力,并能充分利用各种硬件加速。
  3. 自动并行和分布式训练: MindSpore提供了自动并行和分布式训练的功能,使得用户可以更轻松地处理大规模数据和模型,并更高效地进行训练。
  4. 生态系统和社区支持: MindSpore致力于建立开放的生态系统,并鼓励社区贡献,这对于一个开源框架来说非常重要,能够帮助用户更好地学习和解决问题。

一些建议和改进方面:

  1. 文档和教程的改进: 文档和教程并不是很详细,希望能够提供更多实用的示例、详细的文档和教程,以帮助用户更快速地上手和解决问题。
  2. 更多的应用场景示例: 提供更多真实场景的示例代码和应用案例,可以帮助用户更好地了解如何在实际项目中应用MindSpore。

6、未来展望:

​ 大模型的内容还是很多的,希望自己能坚持打卡,将后面的内容都学习完,并做出一些有趣好玩的东西来!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1399894.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringMVC(八)处理AJAX请求

一、处理AJAX之准备工作: 首先我们创建一个新的工程: 我们将pom.xml复制过来: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-in…

JVM之java内存区域[1](程序计数器、栈)

文章目录 版权声明零 运行时数据区一 程序计数器1.1 加载阶段1.2 执行阶段1.3 多线程情况 二 栈2.1 java虚拟机栈2.2 java虚拟机栈帧的组成2.2.1 局部变量表2.2.2 操作数栈2.2.3 帧数据 2.3 栈内存溢出2.4 设置帧大小2.5 本地方法栈 版权声明 本博客的内容基于我个人学习黑马程…

OCS2 入门教程(六)- Double Integrator

系列文章目录 前言 双积分器示例是我们最简单的问题。它模拟了一个沿 x 方向移动的一维点质量。模型是线性的&#xff0c;成本函数是二次函数。目标点通过参考管理器模块设置为二次成本。 一、查看文件结构 1.1 ocs2_double_integrator 文件夹 . ├── auto_generated ├─…

Python爬虫时被封IP,该怎么解决?四大动态IP平台测评

在使用 Python 进行爬虫时&#xff0c;很有可能因为一些异常行为被封 IP&#xff0c;这主要是因为一些爬虫时产生的异常行为导致的。 在曾经的一次数据爬取的时候&#xff0c;我尝试去爬取Google地图上面的商家联系方式和地址信息做营销&#xff0c;可是很不幸&#xff0c;还只…

Centos使用Docker搭建自己的Gitlab(社区版和设置汉化、修改密码、设置SSH秘钥)

根据我的经验 部署Gitlab&#xff08;社区版&#xff09; 至少需要2核4g的服务器 带宽3~4M 1. 在自己电脑上安装终端&#xff1a;宝塔ssl终端 或者 FinalShell&#xff0c;根据喜好安装即可 http://www.hostbuf.com/t/988.html http://www.hostbuf.com/downloads/finalshell_w…

华为原生 HarmonyOS NEXT 鸿蒙操作系统星河版 发布!不依赖 Linux 内核

华为原生 HarmonyOS NEXT 鸿蒙操作系统星河版 发布&#xff01;不依赖 Linux 内核 发布会上&#xff0c;余承东宣布&#xff0c;HarmonyOS NEXT鸿蒙星河版面向开发者开放申请。 申请链接 鸿蒙星河版将实现原生精致、原生易用、原生流畅、原生安全、原生智能、原生互联6大极致原…

原型设计 Axure RP 9

Axure RP 9是一款专业的原型设计和协作工具&#xff0c;让用户快速创建高保真度的交互原型&#xff0c;模拟真实的用户界面和交互体验。该软件界面布局合理&#xff0c;易于使用&#xff0c;提供丰富的交互功能和效果&#xff0c;如动态面板、变量、条件逻辑、动画等。同时支持…

DFA有穷自动机敏感词过滤算法

1.EndType package com.example.utils.wordfilter;/*** 结束类型定义*/ public enum EndType {/*** 有下一个&#xff0c;结束*/HAS_NEXT, IS_END } 2.WordType package com.example.utils.wordfilter;/*** 词汇类型*/ public enum WordType {/*** 黑名单/白名单*/BLACK, WH…

JS-WebAPIs-本地存储(五)

• 本地存储介绍 以前我们页面写的数据一刷新页面就没有了&#xff0c;是不是&#xff1f;随着互联网的快速发展&#xff0c;基于网页的应用越来越普遍&#xff0c;同时也变的越来越复杂&#xff0c;为了满足各种各样的需求&#xff0c;会经常 性在本地存储大量的数据&#xf…

python类继承之__init__函数覆盖问题

目录 1.问题描述 2.代码演示 3.总结 在Python这个广受欢迎的编程语言中&#xff0c;类继承是一项强大而精巧的特性。通过类继承&#xff0c;我们可以构建出更加灵活、可重用和易维护的代码&#xff0c;同时实现代码的模块化和扩展性。 但是如果对于熟悉C和java的人而言&…

Flink实战之运行架构

本文章&#xff1a;重点是分析清楚运行架构以及并行度与slot的分配 1、JobManager和TaskManager Flink中的节点可以分为JobManager和TaskManager。 JobManager处理器也称为Master&#xff0c;用于协调分布式任务执行。他们用来调度task进行具体的任务。TaskManager处理器也称…

蓝桥杯真题(Python)每日练Day2

题目 题目分析 对于本题首先确定其数据结构为优先队列&#xff0c;即邮费最小的衣服优先寄&#xff0c;算法符合贪心算法。可以直接使用queue库的PriorityQueue方法实现优先队列。关于PriorityQueue的使用方法主要有&#xff1a; import queue q queue.Queue()# 队列 pq qu…

【JavaEE】文件操作 —— IO

文件操作 —— IO 1. 文件的属性 文件内容文件大小文件路径文件名称 2. 文件的管理 采用树形结构进行管理。 3. 文件路径 分为两种&#xff1a;相对、绝对路径。 相对路径&#xff1a;相对于当前位置的路径&#xff0c;以“./xxx.xxx”为标志绝对路径&#xff1a;以从盘符…

【工具使用-win10最近使用的文件】怎样关闭win10系统最近使用的文件功能

一&#xff0c;简介 有时候我们不想打开文件管理器的时候&#xff0c;就出现之前访问过的文件或者文件夹&#xff0c;本文就介绍在win10系统下如何关闭“最近使用文件”的功能。 二&#xff0c;操作步骤 打开资源管理器&#xff0c;点击“选项” 按照如下步骤操作&#xff…

树结构实战,获取文件夹大小

文件IO是一个耗时操作&#xff0c;要尽量避免频繁读取磁盘。 而我们需要分析磁盘的占用空间&#xff0c;无法避免需要读取&#xff0c;但是期望只通过一次文件IO操作&#xff0c;来获取到所有某个目录下所有文件夹的信息。 所以需要一种方式可以仅进行一轮磁盘操作&#xff0…

【Linux】安装n卡驱动以及可能遇到的问题

文章目录 1.换源以及更新2.安装依赖3. 安装n卡驱动独显与核显切换nvidia-settings消失忘记安装依赖无法进入图形化界面的急救命令行无响应办法 1.换源以及更新 目前&#xff0c;换源完全只需要鼠标点点点就可以完成了&#xff0c;打开应用列表里的Software & Updates&…

vue3-模版引用

模版引用 ref 属性 场景&#xff1a;需要直接访问底层 DOM 元素。 方法&#xff1a;使用特殊的 ref 属性。 <input ref"input">ref 属性 允许我们在一个特定的 DOM 元素或子组件实例被挂载后&#xff0c;获得对它的直接引用。 访问模板引用 小 Demo: 当 i…

rk1126, 实现 yolov8 目标检测

基于 RKNN 1126 实现 yolov8 目标检测 Ⓜ️ RKNN 模型转换 ONNX yolo export model./weights/yolov8s.pt formatonnx导出 RKNN 这里选择输出 concat 输入两个节点 onnx::Concat_425 和 onnx::Concat_426 from rknn.api import RKNNONNX_MODEL ./weights/yolov8s.onnxRKNN_MOD…

flink operator 拉取阿里云私有镜像(其他私有类似)

创建 k8s secret kubectl --namespace flink create secret docker-registry aliyun-docker-registry --docker-serverregistry.cn-shenzhen.aliyuncs.com --docker-usernameops_acr1060896234 --docker-passwordpasswd --docker-emailDOCKER_EMAIL注意命名空间指定你使用的 我…

使用 vsCode创建GO项目

最近回顾了一下go的使用&#xff1a;具体操作看下面的参考连接&#xff0c;下面只描述一些踩过的坑&#xff1a; 1. go安装配置 安装go->配置go环境变量 推荐官网下载&#xff0c;速度很快&#xff1b; 这里需要配置五个参数&#xff1a;GOPATH/GOROOT/Path、GO111MODULE/…