RESCAL张量分解检测YELP数据集
RESCAL(REsultant Scalar product for CAusal Learning)是一种专门用于处理三维张量的分解方法。它主要用于推荐系统、社交网络分析和知识图谱等领域。RESCAL 通过将张量分解成低维表示,有效捕捉不同实体之间的关系。
为什么 RESCAL 可以检测垃圾评论
1. 用户和商品的交互模式:
RESCAL 通过捕捉用户和商品之间的交互模式,可以识别出异常的行为。例如,某个用户通常给出高评分,但突然给出低评分,这可能表明该评论是垃圾评论。
2. 低维表示的学习:
通过学习用户和商品的低维表示,RESCAL 能够发现用户偏好的潜在因素。这些潜在因素可以帮助识别出与正常用户行为不符的评论。
3. 关系建模:
RESCAL 允许通过关系矩阵建模用户与商品之间的复杂关系,这使得模型能够更准确地识别出垃圾评论。比如,用户的评论行为可能与其历史行为、评分分布等有关。
4. 基于阈值的检测:
通过设置评分阈值(如小于 3 的评分),可以简单地将低评分评论标记为垃圾评论。RESCAL 可以帮助提高这种阈值检测的准确性,因为它提供了更丰富的上下文信息。
Yelp 数据集通常是稀疏的,即大多数用户只对少数商家进行评分。这种稀疏性使得模型需要能够有效地从有限的交互中学习用户和商家之间的关系。RESCAL 张量分解能够处理稀疏数据,并从中提取潜在的模式。
用户在 Yelp 上的行为多样,例如:
- 不同用户的评分分布可能截然不同。
- 用户可能会对同一商家给出不同的评分,取决于他们的体验和偏好。
Yelp 数据集通常还包含一些标签信息(如商家的类别、位置等),这些信息可以用于增强 RESCAL 模型的输入,帮助捕捉更复杂的交互模式。
这个数据集解压后
关于yelp数据集可以参考这篇文章
Yelp数据集的结构-CSDN博客
构建张量
选择yelp_academic_dataset_review.json 和 yelp_academic_dataset_business.json, 经过下面操作处理json数据,可以扩展它以构建一个三维张量,通常为 用户-商家-评论(用户-商家-评分)。这个张量可以用于 RESCAL 模型,帮助检测垃圾评论。以下是修改后的完整代码示例,包含张量构建的部分。
import pandas as pd
import numpy as npdef process_yelp_data(review_file, business_file):# 加载评论数据reviews = pd.read_json(review_file, lines=True)# 选择所需的字段yelp_data = reviews[['user_id', 'business_id', 'stars', 'text', 'date']]# 数据清洗yelp_data.dropna(inplace=True) # 去除缺失值yelp_data.drop_duplicates(inplace=True) # 去除重复项# 文本预处理(可选)yelp_data['text'] = yelp_data['text'].str.replace('[^\w\s]', '', regex=True).str.lower()# 加载商家数据businesses = pd.read_json(business_file, lines=True)# 合并商家信息yelp_data = yelp_data.merge(businesses[['business_id', 'categories']], on='business_id', how='left')# 保存为 CSV 文件yelp_data.to_csv(output_file, index=False)print(f"Processed data saved to {output_file}")# 构建三维张量(用户-商家-评论)build_tensor(yelp_data)def build_tensor(yelp_data):# 创建用户和商家的索引users = yelp_data['user_id'].unique()businesses = yelp_data['business_id'].unique()user_index = {user: i for i, user in enumerate(users)}business_index = {business: i for i, business in enumerate(businesses)}# 初始化张量n_users = len(users)n_businesses = len(businesses)n_reviews = len(yelp_data)tensor = np.zeros((n_users, n_businesses, n_reviews))# 填充张量for idx, row in yelp_data.iterrows():user_id = user_index[row['user_id']]business_id = business_index[row['business_id']]tensor[user_id, business_id, idx] = row['stars'] # 使用星级作为评分print("Tensor shape:", tensor.shape)# 这里可以进一步处理张量,例如保存或用作模型输入if __name__ == "__main__":review_file = 'yelp_academic_dataset_review.json' # 评论文件路径business_file = 'yelp_academic_dataset_business.json' # 商家文件路径process_yelp_data(review_file, business_file)
张量分解
添加方法进行张量分解(RESCAL) perform_tensor_decomposition(tensor)
from tensorly.decomposition import parafacdef perform_tensor_decomposition(tensor):# 设置分解的秩rank = 5 # 可以根据需要调整# RESCAL 张量分解factors = parafac(tensor, rank=rank)# 输出分解结果for i, factor in enumerate(factors):print(f"Factor {i} shape: {factor.shape}")
rank = 5
指定了分解的秩,代表将张量分解成的因子数量。秩越高,保留的信息越多,但计算复杂性和内存需求也会增加。
先尝试运行下有报错
File "/opt/chenrui/yelp/process_yelp_with_tensor.py", line 44, in build_tensor
tensor = np.zeros((n_users, n_businesses, n_reviews))
ValueError: array is too big; `arr.size * arr.dtype.itemsize` is larger than the maximum possible size.
需要检查张量的维度:在构建张量之前,打印用户数、商家数和评论数,以确认它们的大小。如果某个维度特别大,可能会导致内存问题。修改代码
import pandas as pd
import numpy as np
import tensorly as tl
from tensorly.decomposition import parafac
from scipy.sparse import coo_matrixdef process_yelp_data(review_file, business_file):# 加载商家数据businesses = pd.read_json(business_file, lines=True)business_ids = businesses['business_id'].unique()# 合并商家信息all_data = []for reviews_chunk in pd.read_json(review_file, lines=True, chunksize=10000):yelp_data = reviews_chunk[['user_id', 'business_id', 'stars', 'text', 'date']]yelp_data.dropna(inplace=True)yelp_data.drop_duplicates(inplace=True)yelp_data['text'] = yelp_data['text'].str.replace('[^\w\s]', '', regex=True).str.lower()yelp_data = yelp_data[yelp_data['business_id'].isin(business_ids)]all_data.append(yelp_data)# 合并所有数据块yelp_data = pd.concat(all_data, ignore_index=True)tensor = build_tensor(yelp_data)perform_tensor_decomposition(tensor)def build_tensor(yelp_data):users = yelp_data['user_id'].unique()businesses = yelp_data['business_id'].unique()user_index = {user: i for i, user in enumerate(users)}business_index = {business: i for i, business in enumerate(businesses)}row_indices = []col_indices = []data = []for idx, row in yelp_data.iterrows():user_id = user_index[row['user_id']]business_id = business_index[row['business_id']]row_indices.append(user_id)col_indices.append(business_id)data.append(float(row['stars']))sparse_tensor = coo_matrix((data, (row_indices, col_indices)), shape=(len(users), len(businesses)))return sparse_tensordef perform_tensor_decomposition(sparse_tensor):# 将稀疏矩阵转换为密集格式dense_tensor = sparse_tensor.toarray()rank = 5 # 可以根据需要调整factors = parafac(dense_tensor, rank=rank)# 保存因子到文件for i, factor in enumerate(factors):factor_df = pd.DataFrame(factor)factor_df.to_csv(f"factor_{i}.csv", index=False)print(f"Factor {i} saved to factor_{i}.csv")if __name__ == "__main__":review_file = 'yelp_academic_dataset_review.json'business_file = 'yelp_academic_dataset_business.json'process_yelp_data(review_file, business_file)
代码调整说明
-
使用稀疏矩阵:使用
scipy.sparse.coo_matrix
创建稀疏矩阵,这样可以有效地存储稀疏数据,避免内存溢出。 -
转换为 TensorLy 张量:将稀疏矩阵转换为 NumPy 数组后,再将其转换为 TensorLy 张量。
运行还有报错
ImportError: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by /opt/miniconda3/envs/lora/lib/python3.10/site-packages/scipy/optimize/_group_columns.cpython-310-x86_64-linux-gnu.so)
系统中缺少所需版本的 libstdc++
库。这通常发生在使用较旧版本的 Linux 发行版或者 Conda 环境中库文件不匹配的情况下,不过一般ocnda都会装有这个,所以直接locate libstdc++.so.6
找conda地址的libstdc++.so.6 , 用strings 该位置的libstdc++.so.6 文件带上grep GLIBC
看有没有满足的, 我刚好在这个文件里找到/var/lib/snapd/snap/core22/1122/usr/lib/x86_64-linux-gnu/libstdc++.so.6, 把这个路径添加到LD_LIBRARY_PATH 里
再次运行代码,发现代码在处理数据时仍然导致内存耗尽,可能是因为数据集非常大,或者在创建和处理稀疏矩阵时存在问题。做了些优化帮助解决内存问题。
优化代码和处理大数据集
-
分批处理数据:考虑逐行处理或分批加载数据,以减少内存占用。
-
使用生成器:使用生成器按需加载数据,避免将整个数据集加载到内存中。
-
减少张量的维度:在构建张量时考虑只使用重要的用户或商家,以减少维度。
-
优化数据类型:确保使用合适的数据类型(将评分转换为
float32
而不是float64
)。
打印张量分解因子
-
在张量分解中得到的因子全为零或者相同的值分解秩设置不当:
选择的分解秩(rank
)可能不合适。过低的秩可能无法捕捉到数据的复杂性,而过高的秩可能导致过拟合。 rank = 3 后续尝试更小的秩
在张量分解中,求解出的因子(factors)具有重要的实际应用和理论意义。以下是因子的主要作用和用途:
1. 特征提取
- 潜在特征:因子表示了数据中的潜在特征。在用户-商家评分的上下文中,因子可以表示用户的偏好模式或商家的特征。
后面会把用户因子,商家因子和样本数据水平堆叠
X = np.hstack((user_factors, business_factors, X_text.toarray()))
- 降维:通过分解,您可以将高维数据映射到低维空间,有助于简化模型和后续分析。
2. 推荐系统
- 个性化推荐:因子可以用于构建个性化推荐系统。通过分析用户和商家的因子,可以预测用户对未评分商家的可能评分,从而提供推荐。
- 协同过滤:因子分解可以作为协同过滤的一种实现方式,利用用户之间或商家之间的相似性进行推荐。
3. 数据压缩
- 存储效率:因子能够有效地压缩原始数据,降低存储需求。您可以使用较少的因子重构接近原始数据的张量。
- 处理速度:在需要处理大规模数据时,使用因子进行计算通常比处理原始数据要快得多。
4. 数据分析与可视化
- 模式识别:因子可以帮助识别数据中的模式和趋势。例如,可以通过因子分析识别出用户偏好的变化。
- 可视化:将因子可视化可以帮助理解数据中的结构和关系。
垃圾评论检测
在对 Yelp 数据集进行张量分解并获得分解后的因子后,您可以利用这些因子进行垃圾评论检测。以下是一个可能的流程:
1. 定义垃圾评论的标准
首先,您需要定义什么是“垃圾评论”。常见的标准包括:
- 低评分的评论(例如星级评分低于某个阈值)
- 包含特定关键字或短语的评论
- 重复评论或极短的评论
2. 使用因子进行特征提取
根据您的 RESCAL 张量分解,您可以从分解后的因子中提取特征。以下是提取特征的一些方法:
- 用户特征:用户在因子中的表示,可以反映用户的评论风格和偏好。
- 商家特征:商家在因子中的表示,可以反映商家的质量和评价分布。
- 评论特征:对每个评论的特征进行建模,例如使用文本分析方法(如 TF-IDF 或词嵌入)。
3. 构建机器学习模型
使用提取的特征来训练机器学习模型,以进行垃圾评论检测。以下是一个简单的步骤:
3.1 数据准备
将低评分的评论标记为垃圾评论,其他评论标记为正常评论。您可以使用 Pandas 来处理这个数据集:
import pandas as pd# 假设已经有评论数据 yelp_data
yelp_data['is_spam'] = yelp_data['stars'] < 3 # 低于3星的评论标记为垃圾评论
特征提取
从分解的因子和评论文本中提取特征。下面是一个简单的示例:
from sklearn.feature_extraction.text import TfidfVectorizer# 使用 TF-IDF 提取评论文本特征
vectorizer = TfidfVectorizer()
X_text = vectorizer.fit_transform(yelp_data['text'])# 将因子表示和文本特征结合
X = np.hstack((user_factors, business_factors, X_text.toarray())) # 需要根据具体因子的形状调整
y = yelp_data['is_spam'].astype(int)
训练模型
使用机器学习模型进行训练,例如随机森林、支持向量机或深度学习模型:
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 训练模型
model = RandomForestClassifier()
model.fit(X_train, y_train)# 评估模型
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred))