在前一篇測試中我們測試了在本機, Colab, 與 Gradio Playground 建立網頁應用程式的方法, 並且使用 Gradio Playground 可將 Web app 一鍵佈署至 Hugging Face Space 儲存空間. 但前一篇只是以最簡單的說 Hello 為範例, 事實上, Gradio 提供了豐富的輸出入元件可支援文字, 圖像, 影片, 與音訊等媒體形式, 本篇要測試的是 Gradio 的輸入元件.
本系列之前的文章參考 :
Gradio 教學文件參考 :
以下測試皆在 Gradio Playground 上進行, 網址如下 :|
測試範例程式碼則放在 Hugging Face Space :
六. Gradio 的輸出入元件 :
Gradio 的輸入元件類別非常豐富, 支援各種資料型態, 摘要如下表 :
輸入元件類別 | 說明 |
Textbox 簡寫 'text' 或 'texbox' | 用於接收使用者的文字輸入, 傳入參數 : value: 預設值 (預設值 "") label: 標籤 (預設值 None) lines: 行數 (預設值 1) placeholder: 提示文字 (預設值 None) type: "text" 或 "password" (輸入會被遮蔽) |
TextArea 簡寫 'textarea' | 用於接收使用者的多行文字輸入, 傳入參數 : value: 預設值 (預設值 "") label: 標籤 (預設值 None) lines: 初始顯示列數 (預設值 7, 輸入列數超過時會自動增加顯示列數) max_lines: 限制最大顯示列數 (輸入列數超過不會增加高度, 預設 None) placeholder: 提示文字 (預設值 None) |
Number 簡寫 'number' | 接收數值 (整數或浮點數) 輸入, 傳入參數 : value: 預設值 (預設值 None) label: 標籤 (預設值 None) minimum: 最小值 (預設值 None) maximum: 最大值 (預設值 None) |
Slider 簡寫 'slider' | 用於選擇數字範圍內的值的滑桿元件, 傳入參數 : value: 預設值 (預設值 50) label: 標籤 (預設值 None) minimum: 最小值 (預設值 0) maximum: 最大值 (預設值 100) step: 步長 (預設值 1) |
Checkbox 簡寫 'checkbox' | 核取方塊, 用來設定勾選 (True) / 未勾選 (False), 預設未勾選 : value: 初始值 True/False (預設值 False 未勾選) label: 標籤 (預設值 None) info: 選項上方的說明文字 (預設值 None) interactive: 是否可勾選 True/False (預設 True) |
CheckboxGroup 簡寫 'checkboxgroup' | 多選之核取方塊, 用來設定勾選 (True) / 未勾選 (False), 預設均未勾選 : value: 預設值串列 (預設值 []) label: 元件標籤 (預設值 None) choices: 選項串列 (必要參數) info: 選項群組上方, 元件標籤下方的說明文字 (預設值 None) interactive: 是否可勾選 True/False (預設 True) |
Radio 簡寫 'radio' | 單選按鈕, 用於從多個選項中選擇一個, 傳入參數 : value: 預設值串列 (預設值 None) label: 標籤 (預設值 None) choices: 選項串列 (預設值 []) |
Dropdown 簡寫 'dropdown' | 下拉式選單, 用於從多個選項中選擇一個 (與 Radio 一樣), 傳入參數 : value: 預設值串列 (預設值 None) label: 標籤 (預設值 None) choices: 選項串列 (預設值 []) |
Image 簡寫 'image' | 接收圖片輸入 (可拍照或上傳圖片), 支援 PNG, JPEG 等格式, 傳入參數 : value: 本機的圖片路徑檔名或網路圖檔的 URL (預設值 None) label: 標籤 (預設值 None) tool: "sketch" 為繪圖板 (輸入), "editor" 為編輯器, None 為拖曳上傳 (預設) type: 傳回的資料類型, 值 'numpy' 或 'pil' 或 'filepath' (預設值) sources: 圖片輸入來源串列 (預設值 ['upload', 'webcam', 'clipboard']) width: 指定圖片寬度 (px) height: 指定圖片高度 (px) |
Audio 簡寫 'audio' | 接收音訊輸入, 可拖曳/上傳音訊檔或用麥克風錄音 value: 本機的圖片路徑檔名或網路圖檔的 URL (預設值 None) label: 標籤 (預設值 None) sources: 音訊輸入來源串列 (預設值 ['upload', 'microhone']) |
Video 簡寫 'video' | 接收視訊輸入, 可 拖曳/上傳視訊檔或用 webcam 錄影 value: 本機的影片路徑檔名或網路視訊檔的 URL (預設值 None) label: 標籤 (預設值 None) sources: 視訊輸入來源串列 (預設值 ['upload', 'webcam']) width: 指定影片寬度 (px) height: 指定影片高度 (px) |
JSON 簡寫 'json' | 接收 JSON 格式的輸入 label: 元件標籤 (預設值 None) value: 預設值 (預設值 None) |
TimeSeries 簡寫 'timeseries' | 接收時間序列資料輸入 (立如 CSV 格式) label: 元件標籤 (預設值 None) x: x 軸標籤 (預設值 None) y: y 軸標籤 (預設值 None) |
JSON 簡寫 'json' | 接收 JSON 格式的輸入 label: 元件標籤 (預設值 None) value: 預設值 (預設值 None) |
Dataframe 簡寫 'dataframe' | 接收表格格式輸入 (支援文字和數字) label: 元件標籤 (預設值 None) headers: 表格欄名 row_count: 列數 (預設值 (1, 'dynamic')) col_count: 欄數 (預設值 (1, 'dynamic')) |
ColorPicker 簡寫 'colorpicker' | 顏色選擇器 (16 進制) label: 元件標籤 (預設值 None) value: 預設值 (預設值 None) |
Gradio 輸出元件超過 10 個, 有一些輸入元件例如 Textbox, Audio 等也兼做輸出元件用, 但在機器/深度學習應用方面最常用的是 Textbox 與 Label 元件, 常用輸出元件如下表 :
輸出元件類別 | 說明 |
Textbox 簡寫 'text' 或 'texbox' | 用於顯示處理函式傳回的結果, 傳入參數 : value: 預設值 (預設值 "") label: 元件標籤 (預設值 None) lines: 行數 (預設值 1) placeholder: 提示文字 (預設值 None) type: "text" 或 "password" (輸入會被遮蔽) |
Lebel | 用於顯示用於機器學習分類器的結果 (分類標籤及其機率), 傳入參數 : label: 元件標籤 (預設值 None) num_top_classes: 顯示前幾個分類 type: 輸出型態 'value'=分類標籤, 'confidence'=信心, 'auto'=系統決定 (預設) |
Number 簡寫 'number' | 顯示數值 (整數或浮點數) 輸出, 傳入參數 : value: 預設值 (預設值 None) label: 元件標籤 (預設值 None) |
Image 簡寫 'image' | 顯示圖片 label: 元件標籤 (預設值 None) width: 指定圖片寬度 (px) height: 指定圖片高度 (px) |
Audio 簡寫 'audio' | 播放音訊 label: 標籤 (預設值 None) interactive: 是否允許用戶播放 (True/False) |
Video 簡寫 'video' | 播放視訊 label: 元件標籤 (預設值 None) width: 指定影片寬度 (px) height: 指定影片高度 (px) |
JSON 簡寫 'json' | 顯示 JSON 資料 label: 元件標籤 (預設值 None) value: 預設值 (預設值 {}) |
DataFrame 簡寫 'dataframe' | 顯示表格資料 label: 元件標籤 (預設值 None) headers: 表格欄名 |
LinePlot 簡寫 'plot' | 繪製折線圖 value: 要繪製的資料 (dataframe 或二維 ndarray) x: X 軸資料欄名 y: Y 軸資料欄名 title: 圖形標題 color: 顏色分群之欄名 xlabel: X 軸標籤 ylabel: Y 軸標籤 interactive: 是否互動式 (True/False) |
ScatterPlot 簡寫 'scatter' | 繪製折線圖 value: 要繪製的資料 (dataframe 或二維 ndarray) x: X 軸資料欄名 y: Y 軸資料欄名 title: 圖形標題 color: 顏色分群之欄名 xlabel: X 軸標籤 ylabel: Y 軸標籤 grouped: 是否分群 True/False (預設 False) stacked: 是否堆疊 True/False (預設 True) interactive: 是否互動式 (True/False) |
BarPlot 簡寫 'bar' | 繪製折線圖 value: 要繪製的資料 (dataframe 或二維 ndarray) x: X 軸資料欄名 y: Y 軸資料欄名 title: 圖形標題 color: 顏色分群之欄名 xlabel: X 軸標籤 ylabel: Y 軸標籤 interactive: 是否互動式 (True/False) |
事實上 Gradio 還提供許多繪圖類別, 例如長條圖 BarChart, 散佈圖 ScatterPlot, 區域圖 AreaChart, ... 等等, 但最常用的是折線圖.
下面以三個常見的範例說明 Gradio 輸出入元件的用法 :
1. 從文本中擷取數字 :
此例使用正規表達式 r'-?\d+\.?\d*' 從文本中擷取全部數值以串列傳回, 輸出入元件都是使用 Textbox 元件, 輸入框用來貼上含數字的文本, 輸出框用來顯示結果 :
import gradio as gr
import re
def fetch_numbers(text):
numbers=re.findall(r'-?\d+\.?\d*', text)
return [float(num) for num in numbers]
inputs=gr.Textbox(label='從文本中擷取數字',
lines=7,
placeholder='輸入文數字')
demo=gr.Interface(fn=fetch_numbers,
inputs=inputs,
outputs="textbox")
if __name__ == "__main__":
demo.launch()
此例輸入元件使用 gr.Textbox() 建構式建立, 這樣才能設定 lines 與 placeholder 等參數. 輸出元件不需要設定參數所以直接用簡寫的字串 'text' 或 'textbox' 即可, 輸入 "今天的溫度是30度,明天預計會上升到33.2度,最高可達35." 結果如下 :
此 Web app 放在 Hugging Face Space :
關於正規表示法參考 :
2. 計算 BMI :
BMI 計算公式為 weight/(height*height), 可以設置兩個 Textbox 輸入框來讓使用者填寫身高 weight 與體重 height, 輸出框也是使用 Textbox, 程式碼如下 :
import gradio as gr
def handler(weight, height):
w=float(weight)
h=float(height)/100 # 轉成公斤
BMI=round(w/(h*h), 2) # 取小數後兩位
if BMI < 18.5:
remark='體重太輕'
elif BMI >= 18.5 and BMI < 24:
remark='體重正常'
else:
remark='體重過重'
return BMI, remark
weight=gr.Textbox(label='體重(公斤)')
height=gr.Textbox(label='身高(公分)')
bmi=gr.Textbox(label='BMI 指標')
remark=gr.Textbox(label='評語')
iface=gr.Interface(
fn=handler,
inputs=[weight, height],
outputs=[bmi, remark],
title='BMI 計算器',
description='請輸入身高與體重後按 Submit 鈕',
article='BMI 是世衛組織衡量是否肥胖的健康指標',
flagging_mode='never'
)
iface.launch()
此處由於 Textbox 元件輸入的是字串型態, 故須先呼叫 float() 將其轉成浮點數. 注意, 兩個傳回值 BMI 與 remark 必須與 outputs 參數中的兩個串列元素 bmi 與 remark 次序相互對應, 否則輸出會放錯地方, 結果如下 :
上面程式碼放在 Hugging Face 空間 :
但是此程式輸入框全部使用 Textbox 有個問題, 當使用者輸入含有非數值字元時, 呼叫 float() 會出現錯誤 :
這時 Number 元件就可以派上用場取代 Textbox 元件來防呆了, 程式碼修改如下 :
import gradio as gr
def handler(weight, height):
w=float(weight)
h=float(height)/100
BMI=round(w/(h*h), 2)
if BMI < 18.5:
remark='體重太輕'
elif BMI >= 18.5 and BMI < 24:
remark='體重正常'
else:
remark='體重過重'
return BMI, remark
weight=gr.Number(label='體重(公斤)')
height=gr.Number(label='身高(公分)')
bmi=gr.Textbox(label='BMI 指標')
remark=gr.Textbox(label='評語')
iface=gr.Interface(
fn=handler,
inputs=[weight, height],
outputs=[bmi, remark],
title='BMI 計算器',
description='請輸入身高與體重後按 Submit 鈕',
article='BMI 是世衛組織衡量是否肥胖的健康指標',
flagging_mode='never'
)
iface.launch()
這樣體重與身高這兩個輸入框就只能輸入數值, 無法輸入像 '公斤', '公分' 這種非數值字元了, 而且右邊還會出現上下調整小按鈕可用漸增與漸減方式改變輸入值, 結果如下 :
此例程式碼放在 Hugging Face 空間 :
3. 攝氏與華氏溫度轉換 :
攝氏轉華氏公式 : f=c*9/5 + 32
華氏轉攝氏公式 : c=(f-32)*5/9
此處使用一個 Radio 元件選擇輸入的溫度是攝氏還是華氏, 然後用一個 Slider 滑桿元件來輸入溫度數值, 輸出則是使用 Textbox 元件來顯示兩種溫度制的對應轉換結果字串, 程式碼如下 :
import gradio as gr
def handler(sel, temp):
if sel == '攝氏':
c=temp
f=int(c*9/5 + 32) # 轉成整數
msg=f'攝氏 {c} 度=華氏 {f} 度'
else:
f=temp
c=int((f-32)*5/9) # 轉成整數
msg=f'華氏 {f} 度=攝氏 {c} 度'
return msg
sel=gr.Radio(label='溫度制', value='攝氏', choices=['攝氏', '華氏'])
temp=gr.Slider(label='溫度', value=0, minimum=-100, maximum=100)
output=gr.Textbox(label='轉換結果')
iface=gr.Interface(
fn=handler,
inputs=[sel, temp],
outputs=[output],
title='攝氏與華氏溫度轉換',
description='請選擇溫度制與移動溫度滑桿',
flagging_mode='never',
article='攝氏轉華氏公式 : f=c*9/5 + 32<br>' +\
'華氏轉攝氏公式 : c=(f-32)*5/9',
live=True
)
iface.launch()
注意, 此處使用 live=True 讓輸入變化可以立即改變輸出結果而毋須按 Submit 鈕, 此設定會自動取消 Submit 鈕. 另外在 article 參數中使用了 HTML 的 <br> 標籤來達成換行, 結果如下 :
此例程式碼放在 Hugging Face 空間 :
如果不想即時輸出結果, 只要將 live=True 這個參數拿掉即可, 這樣就會出現 Submit 按鈕了.