小说人物分析与形象生成
小说人物分析与形象生成
一、前言
随着AI技术的发展,AI从理解内容,走向了自动生成内容,包括AIGC用于作画、图文、视频等多类型的内容创作。AIGC是继 UGC、PGC 之后新型利用AI技术自动生成内容的生产方式。通过此项技术,借助大模型的跨模态综合技术能力,可以激发创意,提升内容多样性,降低制作成本,将会实现大规模应用。本项目中,通过对小说人物形象的分析进行形象的生成,完成AIGC技术的探索应用。
二、人物形象关键词提取
通常来说,对于小说人物形象的描写都是一大段话,而文生图则需要几个描述清晰的Promt词汇,例如少年等,或者一句描述清晰的话,而小说对于形象的描写则偏向于感性,比如病态等,这个时候模型则很难理解这样的Promt输入,所以我们需要使用一些自然语言处理技术生成一些关键词描述,最后产出我们需要的人物形象。
跨模态生成的一些现存的问题。首先是易用性问题。在应用中,用户需要输入文本描述。但事实上,输入文本描述是很复杂的。比如左侧的例子,需要这里密密麻麻的文字才能生成一个图片。再比如右边文心一格的例子上,通用需要这么一大串文字,不管是主体、内容、风格各方面都需要描述才能生成足够好。所以易用性是要进一步提升的。
2.1 文本摘要生成
使用基于启发式规则的算法实现了一个抽取式摘要算法,一篇文章如果要用里面几个句子来代表,那么肯定选择那些拥有更多个与文章信息相关的关键词的那些句子;另外根据从小语文课上讲的中心句概念,文章首位和每个段落首位的句子基本也是中心句;更进一步,我们通过分析,如果文章中某个句子和文章中大部分句子表达的意思都相近,那么这个句子也能很好的作为摘要句子。
因此本文使用关键词信息量、句子位置、句子相似度三个参数来构建一个句子权重的函数,计算所有句子的权重之后按照降序排序,去前面固定比例的句子,然后依据它们在原文中的先后顺序再次进行排序输出,这样就得到我们要的摘要了。其主要思路如下所示:
1、文本切分和文本表示 (切分句子、构建TFIDF矩阵)
2、计算句子权重 (计算位置权重、计算相似度权重)
3、抽取句子权重最高的句子作为摘要
参考链接:使用Python实现一个文本自动摘要工具
import jieba
import numpy as np
import collections
from sklearn import feature_extraction
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
def split_sentence(text, punctuation_list='!?。!?'):
"""
将文本段安装标点符号列表里的符号切分成句子,将所有句子保存在列表里。
"""
sentence_set = []
inx_position = 0 #索引标点符号的位置
char_position = 0 #移动字符指针位置
for char in text:
char_position += 1
if char in punctuation_list:
next_char = list(text[inx_position:char_position+1]).pop()
if next_char not in punctuation_list:
sentence_set.append(text[inx_position:char_position])
inx_position = char_position
if inx_position < len(text):
sentence_set.append(text[inx_position:])
sentence_with_index = {i:sent for i,sent in enumerate(sentence_set)} #dict(zip(sentence_set, range(len(sentences))))
return sentence_set,sentence_with_index
def get_tfidf_matrix(sentence_set,stop_word):
corpus = []
for sent in sentence_set:
sent_cut = jieba.cut(sent)
sent_list = [word for word in sent_cut if word not in stop_word]
sent_str = ' '.join(sent_list)
corpus.append(sent_str)
vectorizer=CountVectorizer()
transformer=TfidfTransformer()
tfidf=transformer.fit_transform(vectorizer.fit_transform(corpus))
# word=vectorizer.get_feature_names()
tfidf_matrix=tfidf.toarray()
return np.array(tfidf_matrix)
def get_sentence_with_words_weight(tfidf_matrix):
sentence_with_words_weight = {}
for i in range(len(tfidf_matrix)):
sentence_with_words_weight[i] = np.sum(tfidf_matrix[i])
max_weight = max(sentence_with_words_weight.values()) #归一化
min_weight = min(sentence_with_words_weight.values())
for key in sentence_with_words_weight.keys():
x = sentence_with_words_weight[key]
sentence_with_words_weight[key] = (x-min_weight)/(max_weight-min_weight)
return sentence_with_words_weight
def get_sentence_with_position_weight(sentence_set):
sentence_with_position_weight = {}
total_sent = len(sentence_set)
for i in range(total_sent):
sentence_with_position_weight[i] = (total_sent - i) / total_sent
return sentence_with_position_weight
def similarity(sent1,sent2):
"""
计算余弦相似度
"""
return np.sum(sent1 * sent2) / 1e-6+(np.sqrt(np.sum(sent1 * sent1)) *\
np.sqrt(np.sum(sent2 * sent2)))
def get_similarity_weight(tfidf_matrix):
sentence_score = collections.defaultdict(lambda :0.)
for i in range(len(tfidf_matrix)):
score_i = 0.
for j in range(len(tfidf_matrix)):
score_i += similarity(tfidf_matrix[i],tfidf_matrix[j])
sentence_score[i] = score_i
max_score = max(sentence_score.values()) #归一化
min_score = min(sentence_score.values())
for key in sentence_score.keys():
x = sentence_score[key]
sentence_score[key] = (x-min_score)/(max_score-min_score)
return sentence_score
def ranking_base_on_weigth(sentence_with_words_weight,
sentence_with_position_weight,
sentence_score, feature_weight = [1,1,1]):
sentence_weight = collections.defaultdict(lambda :0.)
for sent in sentence_score.keys():
sentence_weight[sent] = feature_weight[0]*sentence_with_words_weight[sent] +\
feature_weight[1]*sentence_with_position_weight[sent] +\
feature_weight[2]*sentence_score[sent]
sort_sent_weight = sorted(sentence_weight.items(),key=lambda d: d[1], reverse=True)
return sort_sent_weight
def get_summarization(sentence_with_index,sort_sent_weight,topK_ratio =0.3):
topK = int(len(sort_sent_weight)*topK_ratio)
summarization_sent = sorted([sent[0] for sent in sort_sent_weight[:topK]])
summarization = []
for i in summarization_sent:
summarization.append(sentence_with_index[i])
summary = ''.join(summarization)
return summary
if __name__ == '__main__':
test_text = 'rose.txt'
# with open(test_text,'r', encoding="gb18030") as f:
with open(test_text,'r') as f:
text = f.read()
stop_word = []
with open('StopWords.txt','r') as f:
for line in f.readlines():
stop_word.append(line.strip())
sentence_set,sentence_with_index = split_sentence(text, punctuation_list='!?。!?')
tfidf_matrix = get_tfidf_matrix(sentence_set,stop_word)
sentence_with_words_weight = get_sentence_with_words_weight(tfidf_matrix)
sentence_with_position_weight = get_sentence_with_position_weight(sentence_set)
sentence_score = get_similarity_weight(tfidf_matrix)
sort_sent_weight = ranking_base_on_weigth(sentence_with_words_weight,
sentence_with_position_weight,
sentence_score, feature_weight = [1,1,1])
summarization = get_summarization(sentence_with_index,sort_sent_weight,topK_ratio=0.8)
# print(type(summarization))
# test_text_out = 'rose_out.txt'
# with open(test_text_out,'w') as f:
# f.write(summarization)
print('summarization:\n',summarization)
summarization:
一个很漂亮的女孩子——这是郝仁的第一印象。对方一身挺清凉的打扮,上身穿着件贴身的白色短袖衫,衣领上缀着一片略有些孩子气的塑料小狗装饰,下身则是深色的短裤+休闲鞋,看起来好像一个偷偷翘课出来逛街的女大学生。这个自来熟的女孩子留着一头披肩短发,可能是很喜欢运动吧,皮肤带着些微的小麦色,健康又充满阳光,她的容貌秀丽可人,最让人注意的是那一双灵动的大眼睛,比郝仁见过的任何一双眼睛都充满活力,仿佛整个人的精气神都要从这双眼睛中透出来一样。
2.2 关键词提取
jieba模块的关键词获取可以通过两种方式来获取:
- 在使用jieba分词对文本进行处理之后,可以通过统计词频来获取关键词:jieba.analyse.extract_tags(news, topK=10),获取词频在前10的作为关键词。
- 使用TF-IDF权重来进行关键词获取,首先需要对文本构建词频矩阵,其次才能使用向量求TF-IDF值。
import jieba
import jieba.analyse
text = summarization
promt_texyrank =list()
# 基于TextRank
keywords = jieba.analyse.textrank(text, topK=5, withWeight=True, allowPOS=('ns', 'n', 'vn', 'v'))
for item in keywords:
print(item[0], item[1])
promt_texyrank.append(item[0])
白色 1.0
翘课 0.8915410498073457
出来 0.8867536986126129
着件 0.8553706593637174
短袖衫 0.8453456531844306
import jieba.analyse as analyse
tfidf = analyse.extract_tags
test_text = summarization
# with open(test_text,'r',) as f:
# text = f.read()
promt_tfidf =list()
# TF-IDF 提取关键词
keywords = tfidf(test_text, topK=5, withWeight=True, allowPOS=())
for item in keywords:
print(item[0], item[1])
promt_tfidf.append(item[0])
女孩子 0.22130913022742857
眼睛 0.220014001314
一双 0.194186673114
休闲鞋 0.18867900673428573
郝仁 0.17078239289857142
2.3 小结
通过本小节,我们已经拿到了需要输入的promt,但是我们同时也可以发现提取到的promt并没有非常理想,此处不足之处大概有两个原因,一是对于整个文档的摘要提取,计算句子权重的问题,当然,这段描述文字偏少也是其中的一个问题;二是关键词的提取,并不能非常有效的提取到所有的形容词。在这里可以给大家提供两个优化思路,其一,使用PaddleNLP的摘要提取功能,直接使用其生成的摘要作为输入的promt或者对promt提取关键词之后再输入;其二,使用文心大模型的摘要提取功能,但是字数需要限制在1000字以内,这两种优化方式不是很难,大家可以尝试做一下。
三、人物形象图生成
# -*- coding: utf-8 -*
! pip install wenxin-api
import wenxin_api # 可以通过"pip install wenxin-api"命令安装
from wenxin_api.tasks.text_to_image import TextToImage
wenxin_api.ak = ""
wenxin_api.sk = ""
input_dict = {
"text": promt_tfidf + promt_texyrank + ["超高清,动漫,超细节,唯美,插画,壁纸"],
"style": "二次元", #解锁更多风格后,非必选参数
"resolution":"1024*1024" , #也可设置为 1024*1536、1536*1024
"num": "2", #功能解锁后,可设置的范围为[1,2,3,4,5,6]
}
rst = TextToImage.create(**input_dict)
print(rst)
2023-01-28 11:20:01,006 - model is painting now!, taskId: 13230768, waiting: 2m
{'imgUrls': ['https://wenxin.baidu.com/younger/file/ERNIE-ViLG/0dbd02ced2ee0feb6726c127347e7fceex', 'https://wenxin.baidu.com/younger/file/ERNIE-ViLG/0dbd02ced2ee0feb6726c127347e7fcei4']}
四、总结
AIGC 就是用人工智能来进行内容生产,它的特点是有非常强大的内容生产力,大幅提升内容生产的质量和效率,将来也会极大地丰富大家的数字生活。跨模态内容生成。核心来讲,我们希望用文本的描述来生成视觉的内容。比如说一句话能生成一个图像,或者我们写一篇文章,能把文章自动转成视频。
首先要做文本理解,也就是我们常说的 Prompt 学习,这里面其实主要是要做一些理解,并根据知识进行扩充。当然,最核心的部分还是文生图。文本已经确定下来了,输入到系统里面,效果一定要足够的好。为此,百度提出了 ERNIE-ViLG 2. 0,这是一个知识增强的混合降噪专家模型。
从图文相关性上面来看,在跨模态生成里面,语言跟视觉之间的对应关系要做得很好,才能保证用户说什么就生成什么。技术上主要通过对语言、视觉还有跨模态做一些知识增强,更好的实现跨模态知识之间的映射,从而实现图文相关性的提升
- 点赞
- 收藏
- 关注作者
评论(0)