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的代码:

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++ :

// Implementation of QuickSort() function for array A[] with size N and pivot value P[N/2]
void QS(int *A, int n) { // Function prototype declarationif (n <=1 ) return;   /* If there is only one element in the input Array */// QuickSort() function for array A[] with size N and pivot value P[N/2]else{                      //else statement to check condition of quick sort algorithm.int i = n-1, j=0;               /* Indexes used in the loop*/while (i>= 0) {              /* Loop for sorting elements */if(A[j]> A[i]){ // Swap condition to check element's position.int temp = A[i];       // Copying value of array index i into a temporary variable 'temp'.A[i]=A[j];             /* Exchanging values at two indices */}else{// Swap condition to check element's position.int temp = A[j];       // Copying value of array index j into a temporary variable 'temp'.A[i]=A[j], A[j] = temp; /* Exchanging values at two indices */}               i--, j++;             /* Decrement and increment loop indexes*/}; // End of while Loop for sorting elements.}//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的压缩后的效果。

我们先下载代码:

git clone https://github.com/THUDM/ChatGLM-6B

然后安装其依赖的库:

pip install -r requirements.txt

上面的gpt4all的Python编程接口不支持Windows,而ChatGLM-6B基于Hugging Face Transformer库开发,支持Windows下的Python编程,我们写个代码来调用它吧:

from transformers import AutoTokenizer, AutoModeltokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
model = AutoModel.from_pretrained("THUDM/chatglm-6b-int4-qe", trust_remote_code=True).half().cuda()
model = model.eval()
response, history = model.chat(tokenizer, "用C++实现快速排序", history=[])
print(response)

输出的结果如下:

#include <iostream>
using namespace std;void swap(int& a, int& b) {int temp = a;a = b;b = temp;
}int partition(int arr[], int low, int high) {int pivot = arr[high];int i = (low - 1);for (int j = low; j < high - 1; j++) {if (arr[j] < pivot) {i++;swap(arr[i], arr[j]);}}swap(arr[i+1], arr[high]);return i+1;
}void quicksort(int arr[], int low, int high) {if (low < high) {int pi = partition(arr, low, high);quicksort(arr, low, pi - 1);quicksort(arr, pi + 1, high);}
}int main() {int arr[] = {5, 2, 9, 1, 6, 3, 8};int n = sizeof(arr) / sizeof(arr[0]);quicksort(arr, 0, n-1);cout << arr[0] << endl;return 0;
}

是不是效果还可以?有点chatgpt的意思了吧?

如果你的PyTorch或者Tensorflow的GPU支持装好了的话,这个推理就是用GPU来完成的。我选用了最省显存的4位量化,如果你的显卡更好,可以选择压缩比更低一些的模型。

这里面我们可以引出Transformer时代的门户,hugging face。我们在上面代码中所使用的from的 transformers库,就是hugging face出品的。

from transformers import AutoTokenizer, AutoModel

从上图我们可以看到,Hugging face基本上就是各种Transformer模型的集散地。使用Hugging face的接口,就可以使用基本上所有的开源的大模型。

大模型是如何炼成的

虽然网络权值需要申请,但是Meta的LLaMA大模型的模型代码是开源的。我们来看看LLaMA的Transformer跟我们上一节构造的标准的Transformer有什么区别:

class Transformer(nn.Module):def __init__(self, params: ModelArgs):super().__init__()self.params = paramsself.vocab_size = params.vocab_sizeself.n_layers = params.n_layersself.tok_embeddings = ParallelEmbedding(params.vocab_size, params.dim, init_method=lambda x: x)self.layers = torch.nn.ModuleList()for layer_id in range(params.n_layers):self.layers.append(TransformerBlock(layer_id, params))self.norm = RMSNorm(params.dim, eps=params.norm_eps)self.output = ColumnParallelLinear(params.dim, params.vocab_size, bias=False, init_method=lambda x: x)self.freqs_cis = precompute_freqs_cis(self.params.dim // self.params.n_heads, self.params.max_seq_len * 2)

我们看到,为了加强并发训练,Meta的全连接网络用的是它们自己的ColumnParallelLinear。它们的词嵌入层也是自己做的并发版。

根据层次数,它也是堆了若干层的TransformerBlock。

我们再来看这个Block:

class TransformerBlock(nn.Module):def __init__(self, layer_id: int, args: ModelArgs):super().__init__()self.n_heads = args.n_headsself.dim = args.dimself.head_dim = args.dim // args.n_headsself.attention = Attention(args)self.feed_forward = FeedForward(dim=args.dim, hidden_dim=4 * args.dim, multiple_of=args.multiple_of)self.layer_id = layer_idself.attention_norm = RMSNorm(args.dim, eps=args.norm_eps)self.ffn_norm = RMSNorm(args.dim, eps=args.norm_eps)def forward(self, x: torch.Tensor, start_pos: int, freqs_cis: torch.Tensor, mask: Optional[torch.Tensor]):h = x + self.attention.forward(self.attention_norm(x), start_pos, freqs_cis, mask)out = h + self.feed_forward.forward(self.ffn_norm(h))return out

我们发现,它没有使用标准的多头注意力,而是自己实现了一个注意力类。

class Attention(nn.Module):def __init__(self, args: ModelArgs):super().__init__()self.n_local_heads = args.n_heads // fs_init.get_model_parallel_world_size()self.head_dim = args.dim // args.n_headsself.wq = ColumnParallelLinear(args.dim,args.n_heads * self.head_dim,bias=False,gather_output=False,init_method=lambda x: x,)self.wk = ColumnParallelLinear(args.dim,args.n_heads * self.head_dim,bias=False,gather_output=False,init_method=lambda x: x,)self.wv = ColumnParallelLinear(args.dim,args.n_heads * self.head_dim,bias=False,gather_output=False,init_method=lambda x: x,)self.wo = RowParallelLinear(args.n_heads * self.head_dim,args.dim,bias=False,input_is_parallel=True,init_method=lambda x: x,)self.cache_k = torch.zeros((args.max_batch_size, args.max_seq_len, self.n_local_heads, self.head_dim)).cuda()self.cache_v = torch.zeros((args.max_batch_size, args.max_seq_len, self.n_local_heads, self.head_dim)).cuda()

闹了半天就是支持了并发和加了cache的多头注意力,K,V,Q穿了个马甲,本质上还是多头自注意力。

其它有趣的工程

LM Flow

LM Flow也是最近很火的项目,它是香港科技大学在LLaMA的基础上搞的全流程开源的,可以在单3090 GPU上进行训练的工程。

其地址在:https://github.com/OptimalScale/LMFlow

LMFlow目前的独特价值在于,它提供的流程比较完整。

比如,在目前的开源项目中,LMFlow是少有的提供了Instruction Tuning的工程。

我们来看个Instruction Tuning的例子:

{"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环境下的实验。

小结

  1. 通过对大模型进行剪枝、降秩、量化等手段,我们是可以在资源受限的电脑上运行推理的。当然,性能是有所损失的。我们可以根据业务场景去平衡,如果能用prompt engineer解决最好
  2. HuggingFace是预训练大模型的编程接口和模型集散地
  3. 大模型的基本原理仍然是我们上节学习的自注意力模型

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

  1. 2023年的深度学习入门指南(1) - 从chatgpt入手

    2023年的深度学习入门指南(1) - 从chatgpt入手 2012年,加拿大多伦多大学的Hinton教授带领他的两个学生Alex和Ilya一起用AlexNet撞开了深度学习的大门,从此人类走入了深 ...

  2. 2023年的深度学习入门指南(10) - CUDA编程基础

    2023年的深度学习入门指南(10) - CUDA编程基础 上一篇我们走马观花地看了下SIMD和GPGPU的编程.不过线条太粗了,在开发大模型时遇到问题了肯定还会晕. 所以我们还是需要深入到CUDA中 ...

  3. 2023年的深度学习入门指南(14) - 不能只关注模型代码

    2023年的深度学习入门指南(14) - 不能只关注模型代码 最近,有一张大模型的发展树非常流行: 这个图是相当不错的,对于加深对于Transformer模型编码器.解码器作用的理解,模型的开源和闭源 ...

  4. 2023年的深度学习入门指南(5) - HuggingFace Transformers库

    2023年的深度学习入门指南(5) - HuggingFace Transformers库 这一节我们来学习下预训练模型的封装库,Hugging Face的Transformers库的使用.Huggi ...

  5. 2023年的深度学习入门指南(8) - 剪枝和量化

    2023年的深度学习入门指南(8) - 剪枝和量化 从这一节开始,我们要准备一些技术专项了.因为目前大模型技术还在快速更新迭代中,各种库和实现每天都在不停出现.因为变化快,所以难免会遇到一些问题.对于 ...

  6. 【AI参赛经验】深度学习入门指南:从零开始TinyMind汉字书法识别——by:Link

    各位人工智能爱好者,大家好! 由TinyMind发起的#第一届汉字书法识别挑战赛#正在火热进行中,比赛才开始3周,已有数只黑马冲进榜单.目前TOP54全部为90分以上!可谓竞争激烈,高手如林.不是比赛 ...

  7. 深度学习入门指南:从零开始TinyMind汉字书法识别

    深度学习入门指南:从零开始TinyMind汉字书法识别 这几天在刷这个新出的比赛,受举办方邀请谢了一篇文章,也转到CSDN来和大家分享下吧.话说TinyMind不是被CSDN收购了么,我这算不算把统一 ...

  8. 给初学者的深度学习入门指南

    从无人驾驶汽车到AlphaGo战胜人类,机器学习成为了当下最热门的技术.而机器学习中一种重要的方法就是深度学习. 作为一个有理想的程序员,若是不懂人工智能(AI)领域中深度学习(DL)这个超热的技术, ...

  9. 恭喜你!在25岁前看到了这篇最最靠谱的深度学习入门指南

    戳蓝字"CSDN云计算"关注我们哦! 人工智能(AI)和机器学习(ML)在当下的火热程度我就不多说了,但是真正懂这方面的人又有多少呢? 本文将带你了解人工智能和机器学习的基本知识. ...

最新文章

  1. IOS开发:关于performSelectorXXX的延迟的使用
  2. bzoj29894170: 数列
  3. jdbc操作步骤和preparedStatment相比Statment的好处
  4. Serverless Kubernetes 容器服务介绍
  5. 【CyberSecurityLearning 63】CSRF攻击
  6. 一文教你快速上手PyFlink
  7. ubuntu scp命令或者用root连接ssh提示:Permission denied, please try again.错误
  8. 哪些蔬菜基本不会使用农药?
  9. 一台linux服务器配置多个tomcat应用
  10. ubuntu16.04中ROS-Kinetic报错: not find a package configuration file provided by “gazebo_ros_control“
  11. Axure原型模板CRM客户关系管理系统高保真原型设计
  12. python定时任务_Python定时任务工具--APScheduler
  13. unity code之FBX模型导入与渲染
  14. tcl c语言笔试题,TCL 2019校园招聘备战-求职应聘指南(笔试真题面试经验).pdf
  15. 如何提升自己(一) 谈学习
  16. 201521123091 《Java程序设计》第11周学习总结
  17. js 跨浏览器tab页通信
  18. 几何分布GeometricDistribution
  19. ubuntu14.04安装krita
  20. 大米手机现身了,小米一脸蒙圈?大米好么?好在哪里呢?

热门文章

  1. Hadoop之父祝贺黄色小象十岁生日快乐
  2. 链路汇聚控制协议LACP
  3. 联通开通流量不显示无服务器,史上最全的联通流量自助开通方法!
  4. 实现Linux和Windows之间复制粘贴
  5. js高级04-- 沙箱模式、函数的4种调用模式(call()、apply())、构造函数的return关键字
  6. 国美电器SAP ERP系统抗压记
  7. 我相信,青春没有地平线
  8. Flink的两阶段提交
  9. 企业如何两步实现数据资产化?
  10. 软件工程- 第3章 传统软件工程方法学