本文使用 Streamlit 和分类器实现了一个应用程序完成无样本分类,看看 Twitter 网友的评论怎么看待苹果你品发布。
苹果 15 发布会前段时间刚开完,国外的网友如何看呢,我们今天写一个程序看看国外的网友是个什么态度。
先看结果:
这个分类器App 之前写好的,根据官方一个教程来的,源码文末分享给大家。
分类器
分类器是一种常见的机器学习算法,用于将输入数据分为两个或多个类别。常见的分类器有逻辑回归、支持向量机、决策树、随机森林等。
今天我们这个程序来对语义进行分类,也就是把我们给出的一句话,分类给指定的关键词。
比如:你真是个小可爱,我们来判断他是积极的、消极的、还是开心还是愤怒。
分类数据
我们抓去一些国外苹果微博的网友评论来作为分类数据。
在苹果的置顶帖子(由于没看发布会,这个动画我还是第一次看,是一个📱撞地球的视频)
下面找一些网友们的评论,
抓去前面几十条数据:
好了,数据集有了,接下来实现我们的分类器。
分类器
分类器我们直接使用 HuggingFace 的 API, 使用 valhalla/distilbart-mnli-12-9[1] 这个模型。
这是在 Meta 的 facebook/bart-large-mnli[2] 之上微调实现的,主要进行零样本文本分类。
基于 NLI 的零样本文本分类
一种使用预训练的 NLI 模型作为现成的零样本序列分类器的方法。该方法的工作原理是将要分类的序列作为 NLI 前提,并根据每个候选标签构建假设。
实现
UI 实现
界面很简单,我们就不画原型了,直接看效果来讲:
整个界面左右两份:
标题
这里我们放了图片和标题文本:
c1, c2 = st.columns([0.4, 2])
with c1:
st.image("assets/logo.png", width=100, )
with c2:
st.caption("")
定义样例数据
我们使用数组定义样例数据,这样方便后面测试(当然可以直接在 UI 上输入):
chatlist: list[list[str]] = [
['','','',],
['','','',],
['','','',],
]
比如这样:
当然少不了我们的主角,网友们的评论:
选择框
option = st.selectbox('选择样例数据', [x[0] for x in chatlist], key='option2')
selected = list(filter(lambda x: x[0] == option, chatlist))
selected = selected[0]
template = '\n'.join(selected)
HuggingFace API Key
前面提到使用 HuggingFace 的 API,我们建一个输入框:
API_KEY2 = st.text_input(
"输入你的 🤗 HuggingFace API 令牌",
help="创建 HuggiginFace 帐户后,您可以在设置页面中获取免费的 API 令牌:: https://huggingface.co/settings/tokens",
type='password',
value=os.getenv('HF_API_KEY')
)
API_URL = ("https://api-inference.huggingface.co/models/valhalla/distilbart-mnli-12-9")
本地运行模型
如果大家不想用 API,也可以本地运行模型:(使用 API 则不需要这步)
from transformers import pipeline
classifier = pipeline(
"zero-shot-classification",
model="facebook/bart-large-mnli"
)
sequence_to_classify = "one day I will see the world"
candidate_labels = ['travel', 'cooking', 'dancing']
classifier(sequence_to_classify, candidate_labels)
#{'labels': ['travel', 'dancing', 'cooking'],
# 'scores': [0.9938651323318481, 0.0032737774308770895, 0.002861034357920289],
# 'sequence': 'one day I will see the world'}
更多用法可参考模型主页[3]。
分类词输入选择
st_tags 来实现一个多选提示输入框。
multiselectComponent = st_tags(
label="输入分类词:",
text="Add labels - 6 max",
value=['Positive', 'Negative', 'Neutral', ],
suggestions=['Positive', 'Negative', 'Neutral',],
maxtags=6,
)
输入框和提交
text = st.text_area(
height=200,
key="2",
)
submit_button = st.form_submit_button(label="提交", type='primary')
分类判断
接下来是重点,先实现一个调用 API 方法:
def query(payload):
response = requests.post(API_URL, headers=headers, json=payload)
return response.json()
逐行调用接口,进行分类:
listToAppend = []
for row in linesList:
output2 = query({
"inputs": row,
"parameters": {"candidate_labels": multiselectComponent},
"options": {"wait_for_model": True},
})
import copy
jsonresoult = copy.deepcopy(output2)
jsonresoult = {'sequence': output2['sequence']}
for (i, label) in enumerate(output2['labels']):
jsonresoult[label] = output2['scores'][i]
listToAppend.append(jsonresoult)
df = pd.DataFrame.from_dict(output2)
st.success("✅ Done!")
免费账户接口使用调用限制的,可以参考HF FAQ 速率限制[4],具体多少也没说,不过测试够用了。
输出结果
首先打印下结果,当然别忘了用 mean 函数求平均数,一并打印出来。
整体看起来,网友消极情绪稍微多一点。
st.write(df)
st.write(df.mean(numeric_only=True))
接下来就是画图了,比如 LineArea 和 Bar:
col1, col2 = st.columns(2)
with col1:
st.area_chart(df, x='句子', y=multiselectComponent, color=colors[:len(multiselectComponent)])
with col2:
st.bar_chart(df, x='句子', y=multiselectComponent, color=colors[:len(multiselectComponent)])
我比较喜欢气泡图,但是气泡图需要处理下数据:
• X 轴表示语句坐标
• Y 轴表示得分
• 气泡大小也用得分表示
import plotly.express as px
fig = px.scatter(
df_bubble,
x='index',
y='score',
size='score',
color="label",
log_x=True,
size_max=60,
color_discrete_sequence=colors,
)
st.plotly_chart(fig, theme="streamlit", use_container_width=True)
源码
https://github.com/iDigitalWings/streamlit-classifier.git[5]
引用链接
[1] valhalla/distilbart-mnli-12-9: https://huggingface.co/valhalla/distilbart-mnli-12-9[2] facebook/bart-large-mnli: https://huggingface.co/facebook/bart-large-mnli[3] 模型主页: https://huggingface.co/facebook/bart-large-mnli[4] HF FAQ 速率限制: https://huggingface.co/docs/api-inference/faq#rate-limits[5]: https://github.com/iDigitalWings/streamlit-classifier.git
--- END ---

