LORA微調,讓大模型更平易近人

技術背景

最近和大模型一起爆火的,還有大模型的微調方法。

這類方法只用很少的數據,就能讓大模型在原本表現沒那么好的下游任務中“脫穎而出”,成為這個任務的專家。

而其中最火的大模型微調方法,又要屬LoRA

增加數據量和模型的參數量是公認的提升神經網絡性能最直接的方法。目前主流的大模型的參數量已擴展至千億級別,「大模型」越來越大的趨勢還將愈演愈烈。

這種趨勢帶來了多方面的算力挑戰。想要微調參數量達千億級別的大語言模型,不僅訓練時間長,還需占用大量高性能的內存資源。

為了讓大模型微調的成本「打下來」,微軟的研究人員開發了低秩自適應(LoRA)技術。LoRA 的精妙之處在于,它相當于在原有大模型的基礎上增加了一個可拆卸的插件,模型主體保持不變。LoRA 隨插隨用,輕巧方便。

對于高效微調出一個定制版的大語言模型或者大視覺、大多模態模型來說,LoRA 是最為廣泛運用的方法之一,同時也是最有效的方法之一。

LoRA微調原理是對預訓練模型進行凍結,并在凍結的前提下,向模型中加入額外的網絡層,然后只訓練這些新增網絡層的參數。因為新增參數數量較少,所以finetune的成本顯著下降,同時也能獲得和全模型微調類似的效果。

LoRA方法的核心思想是,這些大型模型其實是過度參數化的,其中的參數變化可以視為一個低秩矩陣。因此,可以將這個參數矩陣分解成兩個較小的矩陣的乘積。在微調過程中,不需要調整整個大型模型的參數,只需要調整低秩矩陣的參數。

有了LoRA這類型的微調方法,可以使得大模型平易近人,可以讓更多小公司或個人使用者能簡單的在我們自己的數據集中調優模型,微調得到我們期望的輸出。

LoRA 簡介

LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGEMODELS 該文章在ICLR2022中提出,說的是利用低秩適配(low-rankadaptation)的方法,可以在使用大模型適配下游任務時只需要訓練少量的參數即可達到一個很好的效果。

由于 GPU 內存的限制,在訓練過程中更新模型權重成本高昂。

例如,假設我們有一個 7B 參數的語言模型,用一個權重矩陣 W 表示。在反向傳播期間,模型需要學習一個 ΔW 矩陣,旨在更新原始權重,讓損失函數值最小。

權重更新如下:W_updated = W + ΔW。

如果權重矩陣 W 包含 7B 個參數,則權重更新矩陣 ΔW 也包含 7B 個參數,計算矩陣 ΔW 非常耗費計算和內存。

由 Edward Hu 等人提出的 LoRA 將權重變化的部分 ΔW 分解為低秩表示。確切地說,它不需要顯示計算 ΔW。相反,LoRA 在訓練期間學習 ΔW 的分解表示,如下圖所示,這就是 LoRA 節省計算資源的奧秘。

img

如上所示,ΔW 的分解意味著我們需要用兩個較小的 LoRA 矩陣 A 和 B 來表示較大的矩陣 ΔW。如果 A 的行數與 ΔW 相同,B 的列數與 ΔW 相同,我們可以將以上的分解記為 ΔW = AB。(AB 是矩陣 A 和 B 之間的矩陣乘法結果。)

這種方法節省了多少內存呢?還需要取決于秩 r,秩 r 是一個超參數。例如,如果 ΔW 有 10,000 行和 20,000 列,則需存儲 200,000,000 個參數。如果我們選擇 r=8 的 A 和 B,則 A 有 10,000 行和 8 列,B 有 8 行和 20,000 列,即 10,000×8 + 8×20,000 = 240,000 個參數,比 200,000,000 個參數少約 830 倍。

當然,A 和 B 無法捕捉到 ΔW 涵蓋的所有信息,但這是 LoRA 的設計所決定的。在使用 LoRA 時,我們假設模型 W 是一個具有全秩的大矩陣,以收集預訓練數據集中的所有知識。當我們微調 LLM 時,不需要更新所有權重,只需要更新比 ΔW 更少的權重來捕捉核心信息,低秩更新就是這么通過 AB 矩陣實現的。

LoRA是怎么去微調適配下游任務的?

流程很簡單,LoRA利用對應下游任務的數據,只通過訓練新加部分參數來適配下游任務。

而當訓練好新的參數后,利用重參的方式,將新參數和老的模型參數合并,這樣既能在新任務上到達fine-tune整個模型的效果,又不會在推斷的時候增加推斷的耗時。

img

圖中藍色部分為預訓練好的模型參數,LoRA在預訓練好的模型結構旁邊加入了A和B兩個結構,這兩個結構的參數分別初始化為高斯分布和0,那么在訓練剛開始時附加的參數就是0。

A的輸入維度和B的輸出維度分別與原始模型的輸入輸出維度相同,而A的輸出維度和B的輸入維度是一個遠小于原始模型輸入輸出維度的值,這也就是low-rank的體現(有點類似Resnet的結構),這樣做就可以極大地減少待訓練的參數了。

在訓練時只更新A、B的參數,預訓練好的模型參數是固定不變的。在推斷時可以利用重參數(reparametrization)思想,將AB與W合并,這樣就不會在推斷時引入額外的計算了。

而且對于不同的下游任務,只需要在預訓練模型基礎上重新訓練AB就可以了,這樣也能加快大模型的訓練節奏。


之前在基地的ChatGPT分享中提到過LLM的工作原理是根據輸入文本通過模型神經網絡中各個節點來預測下一個字,以自回歸生成的方式完成回答。

實際上,模型在整個自回歸生成過程中決定最終答案的神經網絡節點只占總節點的極少一部分。如圖1所示為多級反饋神經網絡,以輸入鷸蚌相爭為例,真正參與運算的節點如下圖2藍色節點所示,實際LLM的節點數有數億之多,我們稱之為參數量。 作者:神州數碼云基地

神經網絡包含許多稠密層,執行矩陣乘法運算。這些層中的權重矩陣通常具有滿秩。LLM具有較低的“內在維度”,即使在隨機投影到較小子空間時,它們仍然可以有效地學習。

假設權重的更新在適應過程中也具有較低的“內在秩”。對于一個預訓練的權重矩陣W0 ∈ Rd×k,我們通過低秩分解W0 + ?W = W0 + BA來表示其更新,其中B ∈ Rd×r,A ∈ Rr×k,且秩r ≤ min(d,k)。在訓練過程中,W0被凍結,不接收梯度更新,而A和B包含可訓練參數。需要注意的是,W0和?W = BA都與相同的輸入進行乘法運算,它們各自的輸出向量在坐標上求和。前向傳播公式如下:h = W0x + ?Wx = W0x + BAx

在圖3中我們對A使用隨機高斯隨機分布初始化,對B使用零初始化,因此在訓練開始時?W = BA為零。然后,通過αr對?Wx進行縮放,其中α是r中的一個常數。在使用Adam優化時,適當地縮放初始化,調整α的過程與調整學習率大致相同。因此,只需將α設置為我們嘗試的第一個r,并且不對其進行調整。這種縮放有助于在改變r時減少重新調整超參數的需求。

LoRa微調ChatGLM-6B

有時候我們想讓模型幫我們完成一些特定任務或改變模型說話的方式和自我認知。作為定制化交付中心的一員,我需要讓“他”加入我們。先看一下模型原本的輸出。

接下來我將使用LoRa微調將“他”變成定制化交付中心的一員。具體的LoRa微調及微調源碼請前往Confluence查看LoRa高效參數微調準備數據集我們要準備的數據集是具有針對性的,例如你是誰?你叫什么?誰是你的設計者?等等有關目標身份的問題,答案則按照我們的需求進行設計,這里列舉一個例子

設置參數進行微調

CUDA_VISIBLE_DEVICES=0 python ../src/train_sft.py \--do_train \--dataset self \--dataset_dir ../data \--finetuning_type lora \--output_dir path_to_sft_checkpoint \--overwrite_cache \--per_device_train_batch_size 4 \--gradient_accumulation_steps 4 \--lr_scheduler_type cosine \--logging_steps 10 \--save_steps 1000 \--learning_rate 5e-5 \--num_train_epochs 3.0 \--plot_loss \--fp16 影響模型訓練效果的參數主要有下面幾個
lora_rank(int,optional): LoRA 微調中的秩大小。這里并不是越大越好,對于小型數據集如果r=1就可以達到很不錯的效果,即便增加r得到的結果也沒有太大差別。
?
lora_alpha(float,optional): LoRA 微調中的縮放系數。
?
lora_dropout(float,optional): LoRA 微調中的 Dropout 系數。
?
learning_rate(float,optional): AdamW 優化器的初始學習率。如果設置過大會出現loss值無法收斂或過擬合現象即過度適應訓練集而喪失泛化能力,對非訓練集中的數據失去原本的計算能力。
?
num_train_epochs(float,optional): 訓練輪數,如果loss值沒有收斂到理想值可以增加訓練輪數或適當降低學習率。 

很好,我們得到了理想的回答,這說明“小州”的人設已經建立成功了,換句話說,圖二中藍色節點(身份信息)的權重已經改變了,之后任何關于身份的問題都會是以“小州”的人設進行回答。

LoRA使用

HuggingFace的PEFT(Parameter-Efficient Fine-Tuning)中提供了模型微調加速的方法,參數高效微調(PEFT)方法能夠使預先訓練好的語言模型(PLMs)有效地適應各種下游應用,而不需要對模型的所有參數進行微調。

對大規模的PLM進行微調往往成本過高,在這方面,PEFT方法只對少數(額外的)模型參數進行微調,基本思想在于僅微調少量 (額外) 模型參數,同時凍結預訓練 LLM 的大部分參數,從而大大降低了計算和存儲成本,這也克服了災難性遺忘的問題,這是在 LLM 的全參數微調期間觀察到的一種現象PEFT 方法也顯示出在低數據狀態下比微調更好,可以更好地泛化到域外場景。

例如,使用PEFT-lora進行加速微調的效果如下,從中我們可以看到該方案的優勢: 在這里插入圖片描述

## 1、引入組件并設置參數
from transformers import AutoModelForSeq2SeqLM
from peft import get_peft_config, get_peft_model, get_peft_model_state_dict, LoraConfig, TaskType
import torch
from datasets import load_dataset
import os
os.environ["TOKENIZERS_PARALLELISM"] = "false"
from transformers import AutoTokenizer
from torch.utils.data import DataLoader
from transformers import default_data_collator, get_linear_schedule_with_warmup
from tqdm import tqdm
?
## 2、搭建模型
?
peft_config = LoraConfig(task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1)
?
model = AutoModelForSeq2SeqLM.from_pretrained(model_name_or_path)
?
## 3、加載數據
dataset = load_dataset("financial_phrasebank", "sentences_allagree")
dataset = dataset["train"].train_test_split(test_size=0.1)
dataset["validation"] = dataset["test"]
del dataset["test"]
?
classes = dataset["train"].features["label"].names
dataset = dataset.map(lambda x: {"text_label": [classes[label] for label in x["label"]]},batched=True,num_proc=1,
)
?
## 4、訓練數據預處理
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)
?
def preprocess_function(examples):inputs = examples[text_column]targets = examples[label_column]model_inputs = tokenizer(inputs, max_length=max_length, padding="max_length", truncation=True, return_tensors="pt")labels = tokenizer(targets, max_length=3, padding="max_length", truncation=True, return_tensors="pt")labels = labels["input_ids"]labels[labels == tokenizer.pad_token_id] = -100model_inputs["labels"] = labelsreturn model_inputs
?
?
processed_datasets = dataset.map(preprocess_function,batched=True,num_proc=1,remove_columns=dataset["train"].column_names,load_from_cache_file=False,desc="Running tokenizer on dataset",
)
?
train_dataset = processed_datasets["train"]
eval_dataset = processed_datasets["validation"]
?
train_dataloader = DataLoader(train_dataset, shuffle=True, collate_fn=default_data_collator, batch_size=batch_size, pin_memory=True
)
eval_dataloader = DataLoader(eval_dataset, collate_fn=default_data_collator, batch_size=batch_size, pin_memory=True)
?
## 5、設定優化器和正則項
optimizer = torch.optim.AdamW(model.parameters(), lr=lr)
lr_scheduler = get_linear_schedule_with_warmup(optimizer=optimizer,num_warmup_steps=0,num_training_steps=(len(train_dataloader) * num_epochs),
)
?
## 6、訓練與評估
?
model = model.to(device)
?
for epoch in range(num_epochs):model.train()total_loss = 0for step, batch in enumerate(tqdm(train_dataloader)):batch = {k: v.to(device) for k, v in batch.items()}outputs = model(**batch)loss = outputs.losstotal_loss += loss.detach().float()loss.backward()optimizer.step()lr_scheduler.step()optimizer.zero_grad()
?model.eval()eval_loss = 0eval_preds = []for step, batch in enumerate(tqdm(eval_dataloader)):batch = {k: v.to(device) for k, v in batch.items()}with torch.no_grad():outputs = model(**batch)loss = outputs.losseval_loss += loss.detach().float()eval_preds.extend(tokenizer.batch_decode(torch.argmax(outputs.logits, -1).detach().cpu().numpy(), skip_special_tokens=True))eval_epoch_loss = eval_loss / len(eval_dataloader)eval_ppl = torch.exp(eval_epoch_loss)train_epoch_loss = total_loss / len(train_dataloader)train_ppl = torch.exp(train_epoch_loss)print(f"{epoch=}: {train_ppl=} {train_epoch_loss=} {eval_ppl=} {eval_epoch_loss=}")
?
## 7、模型保存
peft_model_id = f"{model_name_or_path}_{peft_config.peft_type}_{peft_config.task_type}"
model.save_pretrained(peft_model_id)
?
## 8、模型推理預測
?
from peft import PeftModel, PeftConfig
peft_model_id = f"{model_name_or_path}_{peft_config.peft_type}_{peft_config.task_type}"
config = PeftConfig.from_pretrained(peft_model_id)
model = AutoModelForSeq2SeqLM.from_pretrained(config.base_model_name_or_path)model = PeftModel.from_pretrained(model, peft_model_id)
model.eval()
?
inputs = tokenizer(dataset["validation"][text_column][i], return_tensors="pt")
print(dataset["validation"][text_column][i])
print(inputs)
with torch.no_grad():outputs = model.generate(input_ids=inputs["input_ids"], max_new_tokens=10)print(outputs)print(tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True))?

提問

LoRA 的權重可以組合嗎?

答案是肯定的。在訓練期間,我們將 LoRA 權重和預訓練權重分開,并在每次前向傳播時加入。

假設在現實世界中,存在一個具有多組 LoRA 權重的應用程序,每組權重對應著一個應用的用戶,那么單獨儲存這些權重,用來節省磁盤空間是很有意義的。同時,在訓練后也可以合并預訓練權重與 LoRA 權重,以創建一個單一模型。這樣,我們就不必在每次前向傳遞中應用 LoRA 權重。

weight += (lora_B @ lora_A) * scaling

我們可以采用如上所示的方法更新權重,并保存合并的權重。

同樣,我們可以繼續添加很多個 LoRA 權重集:

weight += (lora_B_set1 @ lora_A_set1) * scaling_set1weight += (lora_B_set2 @ lora_A_set2) * scaling_set2weight += (lora_B_set3 @ lora_A_set3) * scaling_set3...

我還沒有做實驗來評估這種方法,但通過 Lit-GPT 中提供的 scripts/merge_lora.py 腳本已經可以實現。

腳本鏈接:https://github.com/Lightning-AI/lit-gpt/blob/main/scripts/merge_lora.py

  1. 如果要結合 LoRA,確保它在所有層上應用,而不僅僅是 Key 和 Value 矩陣中,這樣才能最大限度地提升模型的性能。

  2. 調整 LoRA rank 和選擇合適的 α 值至關重要。提供一個小技巧,試試把 α 值設置成 rank 值的兩倍。

  3. 14GB RAM 的單個 GPU 能夠在幾個小時內高效地微調參數規模達 70 億的大模型。對于靜態數據集,想要讓 LLM 強化成「全能選手」,在所有基線任務中都表現優異是不可能完成的。想要解決這個問題需要多樣化的數據源,或者使用 LoRA 以外的技術。

LoRA可以用于視覺任務嗎?

可以的,經常結合stable diffusion等大模型進行微調,在aigc中經常使用,下期我們深入分析lora和lora該如何進行優化。

總結

針對LLM的主流微調方式有P-Tuning、Freeze、LoRa、instruct等等。由于LoRa的并行低秩矩陣幾乎沒有推理延遲被廣泛應用于transformers模型微調,另一個原因是ROI過低,對LLM的FineTune所需要的計算資源不是普通開發者或中小型企業愿意承擔的。而LoRa將訓練參數減少到原模型的千萬分之一的級別使得在普通計算資源下也可以實現FineTune。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/19251.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19251.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19251.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【數據結構與算法 | 鏈表篇】力扣876

1. 力扣876 : 鏈表的中間節點 (1). 題 給你單鏈表的頭結點 head ,請你找出并返回鏈表的中間結點。 如果有兩個中間結點,則返回第二個中間結點。 示例 1: 輸入:head [1,2,3,4,5] 輸出:[3,4,5] 解釋:鏈表…

技術架構設計指南:從需求到實現

技術架構是軟件系統的骨架,它決定了系統的性能、可靠性、擴展性等關鍵特性。本文將介紹技術架構設計的一般步驟和方法。 第一步:需求分析 在設計技術架構之前,首先要對系統需求進行全面深入的分析。這包括功能需求、非功能需求(如…

java使用jdbcTemplatep批量插入數據

JdbcTemplate 是 Spring 框架中提供的一個簡化 JDBC 操作的工具類,它封裝了 JDBC 的核心功能,使得開發者能夠更方便、簡潔地進行數據庫操作。 下面是一個使用 JdbcTemplate 進行批量插入的示例: import org.springframework.jdbc.core.Batch…

理解OAuth:服務間的授權機制

理解OAuth:服務間的授權機制 好的,讓我來教你一下關于這個奇怪的東西。 在不同的項目中,認證有很多不同的方式。但在我們深入探討它的使用方式之前,讓我們先來看看它最初的用途。 首先,我們可以從名稱中得到一些線索。“auth”這個詞與什么有關呢?問題是,這里的“aut…

開抖店必須要辦理營業執照嗎?不用營業執照開店的個人店能用嗎?

大家好,我是電商花花。 可能大家都發現了,抖音小店個人店不用營業執照,只憑借身份證就能開店。 但是這個個人店花花并不建議大家去開,雖然說用用身份證也能開店,有效的幫我們減少了開店的成本,但是個人店…

QT基礎初學

目錄 1.什么是QT 2.環境搭建 QT SDK的下載 QT的使用 QT構建項目 快捷指令 QT的簡單編寫 對象樹 編碼問題 組件 初識信號槽 窗口的釋放 窗口坐標體系 1.什么是QT QT 是一個跨平臺的 C 圖形用戶界面庫,支持多個系統,用于開發具有圖形界面的應…

比較kube-proxy模式:iptables還是IPVS?

kube-proxy是任何 Kubernetes 部署中的關鍵組件。它的作用是將流向服務(通過集群 IP 和節點端口)的流量負載均衡到正確的后端pod。kube-proxy可以運行在三種模式之一,每種模式都使用不同的數據平面技術來實現:userspace、iptables…

QT::QNetworkReply類readAll()讀取不到數據的可能原因

程序中,當發送請求時,并沒有加鎖,而是在響應函數中加了鎖,導致可能某個請求的finished信號影響到其他請求響應數據的讀取 connect(reply,&QNetworkReply::finished,this,&Display::replyFinished);參考這篇文章&#xff…

[LLM]從GPT-4o原理到下一代人機交互技術

一 定義 背景:在推出GPT-4o之前,使用語音模式與ChatGPT交流的延遲較長,無法直接觀察語調、多個說話者或背景噪音,且無法輸出笑聲、歌唱或表達情感。 GPT-4o作為OpenAI推出的一款多模態大型語言模型,代表了這一交互技…

聽說京東618裁員?所以日常準備很重要呀

文末有最少必要的面試題,還準備了離線 PDF 版本。 京東也要向市場輸送人才了? 這幾天看到技術群里不少朋友在討論京東裁員相關的信息。 我去看了下京東近期的操作,京東內部考勤調整和午休時間縮短,以及強化打卡機制等管理調整;有…

R可視化:生存分析森林圖

生存分析森林圖 生存分析森林圖 介紹 ggplot2繪制生存分析森林圖加載R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE)library(tidyverse) library(survival) library(survminer) library(tableone) library(forestplot)# rm(list = ls()) options(stringsAsFa…

AMEYA360代理 | 村田電子去寄生電感降噪元件(LCT)特點和規格

株式會社村田制作所(以下簡稱“村田”)開發了行業首款(1)利用負互感(2)、能對從數MHz到1GHz的諧波(3)范圍內電源噪聲進行抑制的去寄生電感降噪元件“LXLC21系列”(以下簡稱“本產品”)。只需將1件本產品連接至電源電路中的電容器,即可消除與本產品連接的電容器的ESL…

鏈表5(考試用)7-5 sdut-C語言實驗-鏈表的逆置

7-5 sdut-C語言實驗-鏈表的逆置 分數 20 全屏瀏覽 作者 馬新娟 單位 山東理工大學 輸入多個整數,以-1作為結束標志,順序建立一個帶頭結點的單鏈表,之后對該單鏈表的數據進行逆置,并輸出逆置后的單鏈表數據。 輸入格式: 輸入…

OpenMv圖片預處理

本博客講述的是獲取一張圖片首先對圖像進行處理,比如畸形矯正,圖像濾波等操作。 1.histeq()自適應直方圖均衡 # 自適應直方圖均衡例子 # # 此示例展示了如何使用自適應直方圖均衡來改善圖像中的對比度。 #自適應直方圖均衡將圖像分割成區域,然后均衡這些區域中的直方圖,…

ubuntu server版 虛擬機根目錄磁盤擴容

之前一直使用桌面版ubuntu,因為項目原因需要拉取的代碼太大了且項目比較多選擇了體量更小的Ubuntu server版,在使用中發現根目錄的磁盤很快就用滿了 如上,明明分配的300G但是/dev/mapper/ubuntu--vg-ubuntu--lv 只有98G都用滿了 server版本與桌面版不同的是在server版安裝的時…

企業數據安全建設需警惕5大陷阱

我們已經生活在一個數字化的時代,那些能夠從數據中獲取最大價值的組織將成為最后的贏家。在數字化轉型和數據民主化的發展背景下,企業開展數據安全保護刻不容緩。 不過,盡管企業在數據保護方面已取得了長足的進步,但數據安全建設…

Chrome DevTools 助力網頁開發:新手入門指南

網頁開發是一個充滿活力的領域,擁有合適的工具將使您事半功倍。Chrome DevTools 正是這樣一個強大的工具套件,它直接內置于您的 Chrome 瀏覽器中。無論您是剛涉足網頁開發的新手,還是希望提升技能的經驗豐富的專業人士,本指南都將…

一篇文章搞懂二叉樹

文章目錄 DP 樹葉的度樹的度節點的層次節點的祖先節點的子孫雙親節點或父節點 樹的表示孩子兄弟表示法雙親表示法樹和非樹樹的應用 二叉樹滿二叉樹完全二叉樹推論二叉樹的存儲以數組的方式以鏈表的方式堆(Heap)堆的分類大根堆和小根堆的作用 二叉樹的遍歷DFS和BFS DP 動態規劃…

HCIA--DHCP: 動態主機配置協議 (復習)

DHCP: 動態主機配置協議 -- 同一分發管理ip地址 基于UDP 67/68端口工作 網絡中存在DHCP的服務器為需要自動生成ip地址的設備分配ip地址;--C/S模型 成為DHCP服務器的條件: 該設備存在接口或網卡連接到所要分發ip地址的廣播域內該接口或網卡必須已經配置…

在WHM中如何調整max_upload_size 參數大小

今日我們在搭建新網站時需要調整一下PHP參數max_upload_size 的大小,我們公司使用的Hostease的美國獨立服務器產品默認5個IP地址,也購買了cPanel面板,因此聯系Hostease的技術支持,尋求幫助了解到如何在WHM中調整PHP參數&#xff0…