2023年的深度学习入门指南(6) - 在你的电脑上运行大模型

[复制链接]
查看703 | 回复0 | 2023-8-23 11:48:24 | 显示全部楼层 |阅读模式
2023年的深度学习入门指南(6) - 在你的电脑上运行大模型

上一篇我们先容了大模型的基础,自注意力机制以及着实现Transformer模块。由于Transformer被PyTorch和TensorFlow等框架所支持,以是我们只要可以或许配置好框架的GPU大概其他加快硬件的支持,就可以运行起来了。
而想运行大模型,恐怕就没有这么轻易了,很有大概你必要一台Linux电脑。由于现在盛行的AI软件一样平常都依靠大量的开源工具,尤其是要举行优化的情况下,很大概必要从源码举行编译。一旦涉及到开源软件和编译这些事故,在Windows上的难度就变成hard模式了。
大部分开辟者自身都是在开源系统上做开辟的,Windows的适配关注得较少,以致完全不关心。虽然从Cygwin, MinGW, CMake到WSL,各方都为Windows上支持大量Linux开源库举行了不少积极,但是就像在Linux上没有Windows那么多游戏一样,这是生态的标题。
我们先选取几个Windows的兼容性稍好的项目,让用Windows的同砚们也可以体验本机的大模型。
Nomic AI gpt4all (基于LLaMA)

2022年末chatgpt横空出世之后,Meta公司认为openai背离了open的宗旨,于是半开放了他们的大模型LLaMA。半开放的缘故起因是,网络的权重文件必要跟Meta公司申请。
LLaMA主要是针对英语质料举行训练,也引用了部分使用拉丁字母和西里尔字母的语言。它的分词器可以支持汉语和日语,但是并没有使用汉语和日语的质料。
由于不并对全部人开放,我们解说LLaMA是没故意义的。但是我们可以实验一些基于LLaMA的项目,好比Nomic AI的gpt4all。
gpt4all的知心之处是针对Windows, M1 Mac和Intel Mac三种平台都举行了适配,固然默认肯定是支持Linux的。而且,推理使用CPU就可以。
下面我们就将其运行起来吧。
起首下载gpt4all的代码:
  1. git clone https://github.com/nomic-ai/gpt4all
复制代码
第二步,下载量化之后的网络权重值文件:https://the-eye.eu/public/AI/models/nomic-ai/gpt4all/gpt4all-lora-quantized.bin
第三步,将下载的gpt4all-lora-quantized.bin放在gpt4all的chat目次下
第四步,运行gpt4all-lora-quantized可实验文件。以Windows平台为例,就是运行gpt4all-lora-quantized-win64.exe。可以在powershell中实验,也可以直接点击。
运行后,当加载完模型之后,我们就可以跟gpt4all对话了:

下面是gpt4all生成的C++快速排序的代码:
   Please generate quick sort algorithm in C++ language
Here’s how you can implement Quick Sort Algorithm using C++ :
  1. // Implementation of QuickSort() function for array A[] with size N and pivot value P[N/2]
  2. void QS(int *A, int n) { // Function prototype declaration
  3.     if (n <=1 ) return;   /* If there is only one element in the input Array */
  4.         // QuickSort() function for array A[] with size N and pivot value P[N/2]
  5.         else{                      //else statement to check condition of quick sort algorithm.
  6.             int i = n-1, j=0;               /* Indexes used in the loop*/
  7.              while (i>= 0) {              /* Loop for sorting elements */
  8.                 if(A[j]> A[i]){ // Swap condition to check element's position.
  9.                     int temp = A[i];       // Copying value of array index i into a temporary variable 'temp'.
  10.                     A[i]=A[j];             /* Exchanging values at two indices */
  11.                 }else{// Swap condition to check element's position.
  12.                     int temp = A[j];       // Copying value of array index j into a temporary variable 'temp'.
  13.                     A[i]=A[j], A[j] = temp; /* Exchanging values at two indices */
  14.                 }               i--, j++;             /* Decrement and increment loop indexes*/
  15.             }; // End of while Loop for sorting elements.
  16.         }//End if statement to check condition QuickSort() function call with array A[] size N & pivot value P[N/2].
复制代码
恭喜你!你终于乐成在本身的电脑上跑起了一个跟chatgpt一样了不得的预训练大模型。
这个模型虽然能力比chatgpt差了不少,但是它的模型来自LLaMA,训练数据部分取自chatgpt的对话记录,接纳了低秩顺应(LoRA: Low-Rank Adaptation)和量化的技能来缩减模型巨细。每一项技能都是现在的前沿技能。
清华团队的单卡大模型:ChatGLM-6B

清华团队的ChatGLM-6B也是一个目的为运行在单GPU卡上的大模型,其底座为1300万参数的ChatGLM。
下图是2022年10月斯坦福大学对当时主要大模型的评测效果:

从上图数据来看,虽然ChatGLM是落后于InstuctGPT的chatgpt,但是从跟其它模型的比力来看气力还不错。
我们就来试试基于ChatGLM的压缩后的效果。
我们先下载代码:
  1. git clone https://github.com/THUDM/ChatGLM-6B
复制代码
然后安装其依靠的库:
  1. pip install -r requirements.txt
复制代码
上面的gpt4all的Python编程接口不支持Windows,而ChatGLM-6B基于Hugging Face Transformer库开辟,支持Windows下的Python编程,我们写个代码来调用它吧:
  1. from transformers import AutoTokenizer, AutoModel
  2. tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
  3. model = AutoModel.from_pretrained("THUDM/chatglm-6b-int4-qe", trust_remote_code=True).half().cuda()
  4. model = model.eval()
  5. response, history = model.chat(tokenizer, "用C++实现快速排序", history=[])
  6. print(response)
复制代码
输出的效果如下:

  1. #include <iostream>
  2. using namespace std;
  3. void swap(int& a, int& b) {
  4.     int temp = a;
  5.     a = b;
  6.     b = temp;
  7. }
  8. int partition(int arr[], int low, int high) {
  9.     int pivot = arr[high];
  10.     int i = (low - 1);
  11.     for (int j = low; j < high - 1; j++) {
  12.         if (arr[j] < pivot) {
  13.             i++;
  14.             swap(arr[i], arr[j]);
  15.         }
  16.     }
  17.     swap(arr[i+1], arr[high]);
  18.     return i+1;
  19. }
  20. void quicksort(int arr[], int low, int high) {
  21.     if (low < high) {
  22.         int pi = partition(arr, low, high);
  23.         quicksort(arr, low, pi - 1);
  24.         quicksort(arr, pi + 1, high);
  25.     }
  26. }
  27. int main() {
  28.     int arr[] = {5, 2, 9, 1, 6, 3, 8};
  29.     int n = sizeof(arr) / sizeof(arr[0]);
  30.     quicksort(arr, 0, n-1);
  31.     cout << arr[0] << endl;
  32.     return 0;
  33. }
复制代码
是不是效果还可以?有点chatgpt的意思了吧?
假如你的PyTorch大概Tensorflow的GPU支持装好了的话,这个推理就是用GPU来完成的。我选用了最省显存的4位量化,假如你的显卡更好,可以选择压缩比更低一些的模型。
这里面我们可以引出Transformer期间的门户,hugging face。我们在上面代码中所使用的from的 transformers库,就是hugging face出品的。
  1. from transformers import AutoTokenizer, AutoModel
复制代码

从上图我们可以看到,Hugging face根本上就是各种Transformer模型的集散地。使用Hugging face的接口,就可以使用根本上全部的开源的大模型。
大模型是怎样炼成的

虽然网络权值必要申请,但是Meta的LLaMA大模型的模型代码是开源的。我们来看看LLaMA的Transformer跟我们上一节构造的标准的Transformer有什么区别:
  1. class Transformer(nn.Module):
  2.     def __init__(self, params: ModelArgs):
  3.         super().__init__()
  4.         self.params = params
  5.         self.vocab_size = params.vocab_size
  6.         self.n_layers = params.n_layers
  7.         self.tok_embeddings = ParallelEmbedding(
  8.             params.vocab_size, params.dim, init_method=lambda x: x
  9.         )
  10.         self.layers = torch.nn.ModuleList()
  11.         for layer_id in range(params.n_layers):
  12.             self.layers.append(TransformerBlock(layer_id, params))
  13.         self.norm = RMSNorm(params.dim, eps=params.norm_eps)
  14.         self.output = ColumnParallelLinear(
  15.             params.dim, params.vocab_size, bias=False, init_method=lambda x: x
  16.         )
  17.         self.freqs_cis = precompute_freqs_cis(
  18.             self.params.dim // self.params.n_heads, self.params.max_seq_len * 2
  19.         )
复制代码
我们看到,为了加强并发训练,Meta的全毗连网络用的是它们本身的ColumnParallelLinear。它们的词嵌入层也是本身做的并发版。
根据条理数,它也是堆了多少层的TransformerBlock。
我们再来看这个Block:
  1. class TransformerBlock(nn.Module):
  2.     def __init__(self, layer_id: int, args: ModelArgs):
  3.         super().__init__()
  4.         self.n_heads = args.n_heads
  5.         self.dim = args.dim
  6.         self.head_dim = args.dim // args.n_heads
  7.         self.attention = Attention(args)
  8.         self.feed_forward = FeedForward(
  9.             dim=args.dim, hidden_dim=4 * args.dim, multiple_of=args.multiple_of
  10.         )
  11.         self.layer_id = layer_id
  12.         self.attention_norm = RMSNorm(args.dim, eps=args.norm_eps)
  13.         self.ffn_norm = RMSNorm(args.dim, eps=args.norm_eps)
  14.     def forward(self, x: torch.Tensor, start_pos: int, freqs_cis: torch.Tensor, mask: Optional[torch.Tensor]):
  15.         h = x + self.attention.forward(self.attention_norm(x), start_pos, freqs_cis, mask)
  16.         out = h + self.feed_forward.forward(self.ffn_norm(h))
  17.         return out
复制代码
我们发现,它没有使用标准的多头注意力,而是本身实现了一个注意力类。
  1. class Attention(nn.Module):
  2.     def __init__(self, args: ModelArgs):
  3.         super().__init__()
  4.         self.n_local_heads = args.n_heads // fs_init.get_model_parallel_world_size()
  5.         self.head_dim = args.dim // args.n_heads
  6.         self.wq = ColumnParallelLinear(
  7.             args.dim,
  8.             args.n_heads * self.head_dim,
  9.             bias=False,
  10.             gather_output=False,
  11.             init_method=lambda x: x,
  12.         )
  13.         self.wk = ColumnParallelLinear(
  14.             args.dim,
  15.             args.n_heads * self.head_dim,
  16.             bias=False,
  17.             gather_output=False,
  18.             init_method=lambda x: x,
  19.         )
  20.         self.wv = ColumnParallelLinear(
  21.             args.dim,
  22.             args.n_heads * self.head_dim,
  23.             bias=False,
  24.             gather_output=False,
  25.             init_method=lambda x: x,
  26.         )
  27.         self.wo = RowParallelLinear(
  28.             args.n_heads * self.head_dim,
  29.             args.dim,
  30.             bias=False,
  31.             input_is_parallel=True,
  32.             init_method=lambda x: x,
  33.         )
  34.         self.cache_k = torch.zeros(
  35.             (args.max_batch_size, args.max_seq_len, self.n_local_heads, self.head_dim)
  36.         ).cuda()
  37.         self.cache_v = torch.zeros(
  38.             (args.max_batch_size, args.max_seq_len, self.n_local_heads, self.head_dim)
  39.         ).cuda()
复制代码
闹了半天就是支持了并发和加了cache的多头注意力,K,V,Q穿了个马甲,本质上照旧多头自注意力。
其它风趣的工程

LM Flow

LM Flow也是近来很火的项目,它是香港科技大学在LLaMA的基础上搞的全流程开源的,可以在单3090 GPU上举行训练的工程。
其地点在:https://github.com/OptimalScale/LMFlow
LMFlow现在的独特价值在于,它提供的流程比力完整。
好比,在现在的开源项目中,LMFlow是少有的提供了Instruction Tuning的工程。
我们来看个Instruction Tuning的例子:
  1. {"id": 0, "instruction": "The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by keeping it concise. Whenever possible, break complex sentences into multiple sentences and eliminate unnecessary words.", "input": "If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know.", "infer30b_before_item": " Output: The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by keeping it concise. Whenever possible, break complex sentences into multiple sentences and eliminate unnecessary words. If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know.\n---\nInput: Input: The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by keeping it concise. Whenever possible, break complex sentences into multiple sentences and eliminate unnecessary words. If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know.\n Output: Output: The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by keeping it concise. Whenever possible, break complex sentences into multiple sentences and eliminate unnecessary words. If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know.\n---\nInput: Input: The sentence you are given might be too wordy, complicated,", "infer30b_after_item": " \n Output: If you have any questions about my rate or need to adjust the scope for this project, please let me know. \n\n", "infer13b_before_item": " The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by keeping it concise. Whenever possible, break complex sentences into multiple sentences and eliminate unnecessary words. If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", "infer13b_after_item": " \n Output: If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know. \n\n", "infer7b_before_item": " The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by keeping it concise. Whenever possible, break complex sentences into multiple sentences and eliminate unnecessary words. If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know.\nInput: The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by keeping it concise. Whenever possible, break complex sentences into multiple sentences and eliminate unnecessary words. If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know.\nOutput: The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by keeping it concise. Whenever possible, break complex sentences into multiple sentences and eliminate unnecessary words. If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know.\nInput: The sentence you are given might be too wordy, complicated, or unclear. Rewrite the sentence and make your writing clearer by", "infer7b_after_item": " \n Output: If you have any questions about my rate or if you find it necessary to increase or decrease the scope for this project, please let me know. \n\n"}
复制代码
这让我们见识到了,原来纠错就是这样搞的。这是LLaMA中所缺少的。
HuggingGPT

近来浙大和微软的团队又推出了充实使用Hugging Face的门户中枢地位的Jarvis工程。

很不幸的是,上面的两个工程,加上前面工程的高级应用,很难在Windows上面完成。我们后面将同一先容这些必要在Linux情况下的实验。
小结


  • 通过对大模型举行剪枝、降秩、量化等本事,我们是可以在资源受限的电脑上运行推理的。固然,性能是有所丧失的。我们可以根据业务场景去均衡,假如能用prompt engineer办理最好
  • HuggingFace是预训练大模型的编程接口和模型集散地
  • 大模型的根本原理仍旧是我们上节学习的自注意力模型

来源:https://blog.csdn.net/lusing/article/details/130051210
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则