首页 > 其他分享 >nlp入门(二) :商品信息可视化与文本分析实战

nlp入门(二) :商品信息可视化与文本分析实战

时间:2023-08-08 10:56:54浏览次数:42  
标签:nlp 商品信息 description title df cat train 可视化 dict

源码请到:自然语言处理练习: 学习自然语言处理时候写的一些代码 (gitee.com)

数据来源:麦卡里价格建议挑战Mercari Price Suggestion Challenge | Kaggle

如果不会使用魔法可以使用百度云

链接:https://pan.baidu.com/s/1EM2MwjX4bLlypLSIJYZqeg?pwd=xqs0
提取码:xqs0

一、加载数据集

拿到数据集后首先对数据集的数据进行一些显示展示,来了解数据集

# 设置pandas显示配置
pd.set_option('display.max_columns', 1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 1000)

train = pd.read_csv('data/train.tsv', sep='\t')
test = pd.read_csv('data/test.tsv', sep='\t')
# 查看数据集大小
print(train.shape)
print(test.shape)
# 查看数据集列名
print(train.dtypes)
# 查看数据集前几行
print(train.head())
# 查看商品价格信息
print(train.price.describe())

二、分析影响价格的因素

经过第一步已经大致了解了数据集的内容以及价格的范围大小及均值,下面我们进一步对影响价格的因素进行分析

2.1 对价格进行对数变换,比较变换后价格的分布情况

由于价格的分布十分的散乱,所以对价格进行对数变换处理

# 对价格进行对数变换,比较转换前和转换后的分布情况
plt.subplot(1, 2, 1)
(train['price']).plot.hist(bins=50, figsize=(20, 10), edgecolor='white', range=[0, 250])
plt.xlabel('price+', fontsize=17)
plt.ylabel('frequency', fontsize=17)
plt.tick_params(labelsize=15)
plt.title('Price Distribution - Training Set', fontsize=17)

plt.subplot(1, 2, 2)
np.log(train['price'] + 1).plot.hist(bins=50, figsize=(20, 10), edgecolor='white')
plt.xlabel('log(price+1)', fontsize=17)
plt.ylabel('frequency', fontsize=17)
plt.tick_params(labelsize=15)
plt.title('Log(Price) Distribution - Training Set', fontsize=17)
plt.show()

可以看出,原数据十分不均衡,高价区区间大数量少,经过对数处理的数据更加符合正态分布

2.2 包邮对价格的影响

接下来分析商户包邮是否对价格产生影响

# 运费承担:大概有55%卖家承担运费
print(train.shipping.value_counts() / len(train))

 可以看出,大概有百分之五十五的商户包邮

# 看下运费不同情况下的价格变化(包邮的价格贵一些)
prc_shipBySeller = train.loc[train.shipping == 0, 'price']
prc_shipByBuyer = train.loc[train.shipping == 1, 'price']
fig, ax = plt.subplots(figsize=(20, 10))
ax.hist(np.log(prc_shipBySeller + 1), color='#8CB4E1', alpha=1.0, bins=50, label='Price when Seller pays Shipping')
ax.hist(np.log(prc_shipByBuyer + 1), color='#007D00', alpha=0.7, bins=50, label='Price when Buyer pays Shipping')
ax.set(title='Histogram Comparison', ylabel='% of Dataset in Bin')
plt.legend()
plt.xlabel('log(price+1)', fontsize=17)
plt.ylabel('frequency', fontsize=17)
plt.title('Price Distribution by Shipping Type', fontsize=17)
plt.tick_params(labelsize=15)
plt.show()

 可以看出,包邮的整体价格比不包邮的价格贵一些

2.3 商品类别对价格的影响

首先我们统计下商品的类别

# 商品类别划分
print('There are %d unique values in the category column' % train['category_name'].nunique())
print(train['category_name'].value_counts()[:5])
print('There are %d items that do not have a label' % train['category_name'].isnull().sum())

可以看出总共有1287种商品,并且展示了数量前五的商品,还有6327件商品没有类别标签,我们处理的时候就忽略这些商品

商品类别太多了,可以看到商品类别结构为主类/子类1/子类2的格式,我们进行拆分,将类别合并一些

# 商品类别太多了,合并一下
def split_cat(text):
    try:
        return text.split("/")
    except:
        return "No Label", "No Label", "No Label"


train['general_cat'], train['subcat_1'], train['subcat_2'] = zip(*train['category_name'].apply(lambda x: split_cat(x)))
print(train.head())
test['general_cat'], test['subcat_1'], test['subcat_2'] = zip(*test['category_name'].apply(lambda x: split_cat(x)))
print('There are %d unique general_cat' % train['general_cat'].nunique())
print('There are %d unique first sub-categories' % train['subcat_1'].nunique())
print('There are %d unique second sub-categories' % train['subcat_2'].nunique())

可以看出总共有11个主类,114个子类1,871个子类2

接下来分析下主类的分布情况

# 主类别分布情况
x = train['general_cat'].value_counts().index.values.astype('str')
y = train['general_cat'].value_counts().values
pct = [('%.2f' % (v * 100)) + '%' for v in (y / len(train))]
tracel = go.Bar(x=x, y=y, text=pct)
layout = dict(title="Number of Items by Main Category", yaxis=dict(title='Count'), xaxis=dict(title='Category'))
fig = dict(data=[tracel], layout=layout)
py.iplot(fig)

可以看出,大量商品是关于女这种类别的,占据了百分之四十五,第二多的是化妆品,第三多的是孩子。

子类的数量很多,我们展示前15个子类的分布

# 前15个子类别分布情况
x = train['subcat_1'].value_counts().index.values.astype('str')[:15]
y = train['subcat_1'].value_counts().values[:15]
pct = [('%.2f' % (v * 100)) + '%' for v in (y / len(train))][:15]
tracel = go.Bar(x=x, y=y, text=pct, marker=dict(color=y, colorscale='Portland', showscale=True, reversescale=False))
layout = dict(title="Number of Items by Sub Category(Top 15)", yaxis=dict(title='Count'),
              xaxis=dict(title='SubCategory'))
fig = dict(data=[tracel], layout=layout)
py.iplot(fig)

 接下来看看不同主类商品的价格区间

# 不同类型商品价格浮动区间
general_cats = train['general_cat'].unique()
x = [train.loc[train['general_cat'] == cat, 'price'] for cat in general_cats]
data = [go.Box(x=np.log(x[i] + 1), name=general_cats[i]) for i in range(len(general_cats))]
layout = dict(title='Price Distribution by General Category', yaxis=dict(title='Frequency'),
              xaxis=dict(title='Category'))
fig = dict(data=data, layout=layout)
py.iplot(fig)

 2.4 品牌分布情况

分析一下品牌的分布情况

# 前10品牌名称的数据分布
x = train['brand_name'].value_counts().index.values.astype('str')[:10]
y = train['brand_name'].value_counts().values[:10]
tracel = go.Bar(x=x, y=y, marker=dict(color=y, colorscale='Portland', showscale=True, reversescale=False))
layout = dict(title="Top 10 Brand by Number of Items", yaxis=dict(title='Count'), xaxis=dict(title='Brand Name'))
fig = dict(data=[tracel], layout=layout)
py.iplot(fig)

2.5 商品描述长度对商品的影响

统计商品描述的长度,然后研究其对商品的影响

# 商品描述对价格的影响
def wordCount(text):
    try:
        text = text.lower()
        regex = re.compile('[' + re.escape(string.punctuation) + '0-9\\r\\t\\n]')
        txt = regex.sub(' ', text)
        words = [w for w in txt.split(" ") if w not in stop_words.STOP_WORDS and len(w) > 3]
        return len(words)
    except:
        return 0


train['desc_len'] = train['item_description'].apply(lambda x: wordCount(x))
test['desc_len'] = test['item_description'].apply(lambda x: wordCount(x))
print(train.head())

df = train.groupby('desc_len')['price'].mean().reset_index()
tracel = go.Scatter(x=df['desc_len'], y=np.log(df['price'] + 1), mode='lines+markers', name='lines+markers')
layout = dict(title='Average Log(Price) by Description Length', yaxis=dict(title='Average Log(Price)'),
              xaxis=dict(title='Description Length'))
fig = dict(data=[tracel], layout=layout)
py.iplot(fig)

 

可以看到商品描述适中价格越高,描述短的可能因为功能简单所以价格低,描述长的可能因为小众所以价格低

三、商品描述关键字

3.1 统计常用关键字

统计一下商品描述中常用的关键字,注意,有的商品没有商品描述,需要去掉

print(train.item_description.isnull().sum())
# 去掉缺失值
train = train[pd.notnull(train['item_description'])]
# 提取每种品牌的描述关键词
tokenize = nltk.data.load('tokenizers/punkt/english.pickle')
cat_desc = dict()
for cat in general_cats:
    text = ' '.join(train.loc[train['general_cat'] == cat, 'item_description'].values)
    cat_desc[cat] = tokenize.tokenize(text)

# 统计常用关键词
flat_lst = [item for sublist in list(cat_desc.values()) for item in sublist]
allWordsCount = Counter(flat_lst)
all_top10 = allWordsCount.most_common(20)
x = [w[0] for w in all_top10]
y = [w[1] for w in all_top10]
tracel = go.Bar(x=x, y=y)
layout = dict(title='Word Frequency', yaxis=dict(title='Count'), xaxis=dict(title='Word'))
fig = dict(data=[tracel], layout=layout)
py.iplot(fig)

 

 

 

3.2 分别展示不同商品的关键字

 首先将商品描述进行分词,去掉停用词

# 展示不同商品的关键词
stop = set(stopwords.words('english'))


def tokenize(text):
    try:
        regex = re.compile('[' + re.escape(string.punctuation) + '0-9\\r\\t\\n]')
        text = regex.sub(' ', text)

        tokens_ = [word_tokenize(s) for s in sent_tokenize(text)]
        tokens = []
        for token_by_sent in tokens_:
            tokens += token_by_sent
        tokens = list(filter(lambda t: t.lower() not in stop, tokens))
        filtered_tokens = [w for w in tokens if re.search('[a-zA-Z]', w)]
        filtered_tokens = [w.lower() for w in filtered_tokens if len(w) >= 3]
        return filtered_tokens
    except TypeError as e:
        print(text, e)


train['tokens'] = train['item_description'].map(tokenize)
test['tokens'] = test['item_description'].map(tokenize)

train.reset_index(drop=True, inplace=True)
test.reset_index(drop=True, inplace=True)
for description, tokens in zip(train['item_description'].head(), train['tokens'].head()):
    print('description:', description)
    print('tokens:', tokens)
    print()

cat_desc = dict()
for cat in general_cats:
    text = ' '.join(train.loc[train['general_cat'] == cat, 'item_description'].values)
    cat_desc[cat] = tokenize(text)

cat_desc100 = dict()
for key, value in cat_desc.items():
    cat_desc100[key] = Counter(value).most_common()


def generate_wordcloud(tup):
    wordcloud = WordCloud(background_color='white', max_words=50, max_font_size=40, random_state=42).generate(str(tup))
    return wordcloud


fig, axes = plt.subplots(len(cat_desc100) // 2 + 1, 2, figsize=(30, 15))

for i, (key, cat) in enumerate(cat_desc100.items()):
    ax = axes[i // 2, i % 2]
    ax.imshow(generate_wordcloud(cat), interpolation='bilinear')
    ax.axis('off')
    ax.set_title("%s Top 100" % key, fontsize=12)

plt.show()

对每个类别提取数量最多的前100个关键字统计词频生成词云

四、tfidf算法

可以看出不同类别出现的关键字有很多是相似的,不能代表这种类别的商品,所以我们使用tf-idf算法进行关键字的挖掘,tf-idf基本思想是词在本文章中出现的次数越多在其他文章中出现的次数越少越可能是关键字。首先将描述数据扩展到180000维度,在进行tf-idf打分

# tf-idf
vectorizer = TfidfVectorizer(min_df=10, max_features=180000, tokenizer=tokenize, ngram_range=(1, 2))
all_desc = np.append(train['item_description'].values, test['item_description'].values)
vz = vectorizer.fit_transform(list(all_desc))
print(vz.shape)

tfidf = dict(zip(vectorizer.get_feature_names_out(), vectorizer.idf_))
tfidf = pd.DataFrame(columns=['tfidf']).from_dict(dict(tfidf), orient='index')
tfidf.columns = ['tfidf']
print(tfidf.sort_values(by=['tfidf'], ascending=True).head(10))
print(tfidf.sort_values(by=['tfidf'], ascending=False).head(10))

 

 

可以看出停用词的得分值基本上都比较低,因为他们虽然频率高但是不具备什么代表性的价值,而另一批的词得分就很高,可以作为关键词来分析

接下来使用SVD降维将特征的维度降到50,然后使用t-SNE将维度降维到2进行展示

trn = train.copy()
tst = test.copy()
trn['is_train'] = 1
tst['is_train'] = 0
sample_sz = 15000
# 采样
combined_df = pd.concat([trn, tst])
combined_sample = combined_df.sample(n=sample_sz)
vz_sample = vectorizer.fit_transform(list(combined_sample['item_description']))
# SVD 降维
n_comp = 30
svd = TruncatedSVD(n_components=n_comp, random_state=42)
svd_tfidf = svd.fit_transform(vz_sample)
# t-SNE降维
tsne_model = TSNE(n_components=2, verbose=1, random_state=42, n_iter=500)
tsne_tfidf = tsne_model.fit_transform(svd_tfidf)

plot_tfidf = bp.figure(width=700, height=600, title='tf-idf clustring of the item description',
                       tools='pan, wheel_zoom, box_zoom, reset, hover', x_axis_type=None, y_axis_type=None,
                       min_border=1)
combined_sample.reset_index(inplace=True, drop=True)
tfidf_df = pd.DataFrame(tsne_tfidf, columns=['x', 'y'])
tfidf_df['description'] = combined_sample['item_description']
tfidf_df['tokens'] = combined_sample['tokens']
tfidf_df['category'] = combined_sample['general_cat']
plot_tfidf.scatter(x='x', y='y', source=tfidf_df, alpha=0.7)
hover = plot_tfidf.select(dict(type=HoverTool))
hover.tooltips = {'description': '@description', 'tokens': '@tokens', 'category': '@category'}
show(plot_tfidf)

 关键词比较接近的就会被绘制在一个点位置

五、分类

5.1 使用聚类算法对上面数据的点可以进行分类

# 聚类分堆
num_clusters = 10
kmeans_model = MiniBatchKMeans(n_clusters=num_clusters, init='k-means++', n_init=1, init_size=10000, batch_size=1000,
                               verbose=0, max_iter=1000)
kmeans_model.fit(vz_sample)
kmeans_clusters = kmeans_model.predict(vz_sample)
kmeans_distances = kmeans_model.transform(vz_sample)
tsne_kmeans = tsne_model.fit_transform(kmeans_distances)

kmeans_df = pd.DataFrame(tsne_kmeans, columns=['x', 'y'])
kmeans_df['cluster'] = kmeans_clusters
kmeans_df['description'] = combined_sample['item_description']
kmeans_df['category'] = combined_sample['general_cat']
plot_kmeans = bp.figure(width=700, height=600, title='KMeans clustering of the description',
                        tools='pan, wheel_zoom, box_zoom, reset, hover', x_axis_type=None, y_axis_type=None,
                        min_border=1)
print(kmeans_clusters)
colormap = {'0': 'red', '1': 'green', '2': 'blue', '3': 'black', '4': 'yellow', '5': 'pink', '6': 'purple', '7': 'grey',
            '8': 'brown', '9': 'orange'}


def get_color(num):
    if num == 0:
        return 'red'
    elif num == 1:
        return 'green'
    elif num == 2:
        return 'blue'
    elif num == 3:
        return 'black'
    elif num == 4:
        return 'yellow'
    elif num == 5:
        return 'pink'
    elif num == 6:
        return 'purple'
    elif num == 7:
        return 'grey'
    elif num == 8:
        return 'brown'
    elif num == 9:
        return 'orange'


color = pd.Series(kmeans_clusters).apply(get_color)
source = ColumnDataSource(
    data=dict(x=kmeans_df['x'], y=kmeans_df['y'], color=color, description=kmeans_df['description'],
              category=kmeans_df['category'], cluster=kmeans_df['cluster']))
plot_kmeans.scatter(x='x', y='y', color='color', source=source)
hover = plot_kmeans.select(dict(type=HoverTool))
hover.tooltips = {'description': '@description', 'category': '@category', 'cluster': '@cluster'}
show(plot_kmeans)

 5.2 LDA主题模型分类

除了聚类算法外,也可以使用LDA主题模型进行分类

# LDA分堆
cvectorizer = CountVectorizer(min_df=4, max_features=180000, tokenizer=tokenize, ngram_range=(1, 2))
cvz = cvectorizer.fit_transform(combined_sample['item_description'])
lda_model = LatentDirichletAllocation(n_components=10, learning_method='online', max_iter=20, random_state=42)
X_topics = lda_model.fit_transform(cvz)

# 获取主题
n_top_words = 10
topic_summaries = []
topic_word = lda_model.components_
vocab = cvectorizer.get_feature_names_out()
for i, topic_dist in enumerate(topic_word):
    topic_words = np.array(vocab)[np.argsort(topic_dist)][:-(n_top_words + 1):-1]
    topic_summaries.append(' '.join(topic_words))
    print('Topic {}:{}'.format(i, '|'.join(topic_words)))

tsne_lda = tsne_model.fit_transform(X_topics)
unnormalized = np.matrix(X_topics)
doc_topic = unnormalized / unnormalized.sum(axis=1)
lda_keys = []
for i, tweet in enumerate(combined_sample['item_description']):
    lda_keys += [doc_topic[i].argmax()]

lda_df = pd.DataFrame(tsne_lda, columns=['x', 'y'])
lda_df['description'] = combined_sample['item_description']
lda_df['category'] = combined_sample['general_cat']
lda_df['topic'] = lda_keys
lda_df['topic'] = lda_df['topic'].map(int)
plot_lda = bp.figure(width=700, height=600, title='LDA topic visualization',
                     tools='pan, wheel_zoom, box_zoom, reset, hover', x_axis_type=None, y_axis_type=None, min_border=1)
source = ColumnDataSource(
    data=dict(x=lda_df['x'], y=lda_df['y'], color=color, description=lda_df['description'],
              topic=lda_df['topic'], category=lda_df['category']))
plot_lda.scatter(x='x', y='y', color='color', source=source)
hover = plot_lda.select(dict(type=HoverTool))
hover.tooltips = {'description': '@description', 'topic': '@topic', 'category': '@category'}
show(plot_lda)

 把不同关键字分为了十个主题

 

标签:nlp,商品信息,description,title,df,cat,train,可视化,dict
From: https://www.cnblogs.com/zhangshihang/p/17613582.html

相关文章

  • OPCClient可视化工具使用教程
    OPCClient可视化工具使用教程1、下载OPCClient,直接打开,进入如下界面: 2、点击OPC=>Connect,ServerNode输入服务器ip,点击RefreshList,下面文本框会出现服务名,选择所需要的服务名称,点击OK或双击服务名3、点击OPC=>AddItem,出现下图4、选择左下框,右框出现所有节点,双击节点即......
  • TextBrewer:融合并改进了NLP和CV中的多种知识蒸馏技术、提供便捷快速的知识蒸馏框架、
    TextBrewer:融合并改进了NLP和CV中的多种知识蒸馏技术、提供便捷快速的知识蒸馏框架、提升模型的推理速度,减少内存占用TextBrewer是一个基于PyTorch的、为实现NLP中的知识蒸馏任务而设计的工具包,融合并改进了NLP和CV中的多种知识蒸馏技术,提供便捷快速的知识蒸馏框架,用于以较低的......
  • 星融元:DPU替代网络可视化专用设备实现业务报文深度处理
    网络可视化中的深度业务处理网络可视化场景中,通常需要将采集过来的数据经过深度业务处理后再交给后端分析系统。这些深度业务处理功能包括:传统的深度业务处理通常由带CPU的框式设备完成,但框式设备成本高、功耗大、扩展不够灵活的种种给客户带来了极大的困扰。DPU算力的池化应用Heli......
  • DataWhale NLP第二期 第一次打卡
    理解赛题,跑通竞赛实践全流程跑通实践基线Baseline,获得自己的成绩提交任务一打卡,查看个人成绩排行榜赛题理解赛题链接本赛题要求构建一个文本分类器,来区分真实对话和由AI产生的对话,训练的数据包括一系列真实对话和ChatGPT生成的对话样本,参赛选手需要设计并训练一个模型,使其......
  • 神经网络可视化工具
    目录1.pipinstallonnx2.根据以下脚本把.pt文件转换成.onnx文件3.在网页打开onnx文件进行可视化展示使用onnx工具能可视化的展示神经网络的结构,便于理解和学习。1.pipinstallonnx2.根据以下脚本把.pt文件转换成.onnx文件"""ExportsaYOLOv5*.ptmodeltoONNXandTorc......
  • (通俗易懂)可视化详解多通道 & 多通道输入输出卷积代码实现
    以前对多通道和多通道输入输出的卷积操作不理解,今天自己在草稿纸上画图推理了一遍,终于弄懂了。希望能帮助到大家。多通道可视化一通道的2x2矩阵torch.Size([2,2])相当于torch.Size([1,2,2]),是一通道的2x2矩阵二通道的2x2矩阵torch.Size([2,2,2])代表二通道的2x2矩阵,第一个2表......
  • VScode+X11支持连接服务器时支持open3d、openCV、matplotlib等可视化
    背景连接服务器以后,想用open3d可视化点云、matplotlib画点图,但是一直不能用,原因也很简单,就是没有配置GUI传输显示,那肯定是要配置X11相关的东西。过程服务器确保服务器下载了xterm、xorg-x11-xauth两个包,不确定可以用dpkg-l加正则表达式查看,应该基本上都有。之后检查/etc/ssh/......
  • GB28181智慧可视化指挥控制系统之执法记录仪设计探讨
    什么是智慧可视化指挥控制系统?智慧可视化指挥控制平台通过4G/5G网络、WIFI实时传输视音频数据至指挥中心,特别是在有突发情况时,可以指定一台执法仪为现场视频监控器,实时传输当前画面到指挥中心,指挥中心工作人员可通过麦克风向现场执法人员下达指令(语音广播或语音对讲)。本文主要介绍......
  • 从机器学习、NLP到GNN,与李开复、陆奇、清华刘知远等共话AI,现开放报名!
     Datawhale会议 人工智能重磅会议:北京智源大会自2009年深度学习崛起以来,第三波人工智能浪潮席卷全球,深度学习、符号主义、联邦学习等等概念推动了新一波技术革命。2020年,是一个十年的结束,也是下一个十年的开始。第二届北京智源大会将于6月21-24日线上开幕。GeoffreyHinto......
  • 自然语言处理(Natural Language Processing,NLP)
    自然语言处理(NaturalLanguageProcessing,NLP)是人工智能领域的一个重要分支,旨在使计算机能够理解、处理和生成人类自然语言。NLP的目标是让计算机能够像人类一样有效地理解和交流,从而实现更自然、更智能的人机交互。NLP的理解概括:文本理解和分析:NLP技术能够从文本中提取有价值......