使用在另一列中找到的值列表预测一列中的相应值

数据挖掘 预测建模 朴素贝叶斯分类器 tfidf
2022-03-12 00:45:28

请看一下这个链接这是我几个月前提出的一个问题,经过一些建议和探索后,我能够成功地使用 TFIDF 和 MultinomialNB 分类器来非常准确地根据Composition列预测“项目”。我自己写了答案来告诉我如何解决它。但这一次,同样的逻辑对类似的数据集并没有帮助。

旧数据:(在上面的链接中引用我之前的示例)

UID    Item               Composition
1      Water              Hydrogen,Oxygen
2      Sulfuric acid      Hydrogen,Sulfur,Oxygen
3      Alcohol            Spirit
4      Hydrochloric acid  Hydrogen,Chloride
5      Citric Acid        Hydrogen,Carbon, Oxygen

新数据示例:

UID    Item                 Composition
1      [Sweater]            [Wool, knitting, handmade, knitting needle]
2      [Jeans]              [Denim, cotton, orange thread, stonewash, blue dye]
3      [CottonTrouser]      [Cotton, littlepolyster, weaving, handstitch, vcut]
4      [SilkShirt]          [wormsilk, artificialsilk, weaving, hand looming, color dying, coating]
5      [Carpet]             [Wool, cotton, organic cotton, knitting, sewing]

这次我有很多这样的数据。Item列中大约有 4200 个此类项目。我正在尝试将 TFIDF 与二元组和三元组一起使用,并使用 MultinomialNB 使算法学习其中的所有项目并准确Composition预测。Item

1)我希望 TF-IDF 在单词级别上使用 n-gram,以便它可以对单词进行矢量化。
2)我希望分类器根据不同的成分对项目进行分类,以便它可以了解哪些成分组合在一起。

对于列中的某些项目Item,它们在列中包含大约 10 个值Composition所以我使用了 min_df=8 和 ngram_range=(1,8),希望它可以尝试构建每个作文大约 8 个单词的词汇表。

from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(sublinear_tf=True, min_df=8, norm='l2', encoding='latin-1', ngram_range=(1,8),     analyzer='word',lowercase=True,stop_words='english')
features = tfidf.fit_transform(dftest.Composition.values.astype('U')).toarray()
labels = dftest.Indexer
features.shape

无论我尝试哪种组合,预测都会出错,并且我注意到 ngram 并没有真正查看Composition列中的单词级别。

我需要关于如何更好地解决这个问题和我的方法中的错误的专家建议。把我当作这个领域的新手。

1个回答

虽然不是一个非常聪明的解决方案。但我设法做了一些技巧让它发挥作用。我对结果并不完全满意,但该算法能够Item根据给定的Composition列准确预测。

from io import StringIO
import json
col = ['Item', 'Composition']
df = dfmin[col]
df['Item'] = df['Item'].apply(lambda x: ''.join(str(x).strip('[]') if      isinstance(x, list) else x))
df['Composition'] = df['Composition'].apply(lambda x: ''.join(str(x).strip('[]') if isinstance(x, list) else x))
df['Composition'] = df['Composition'].apply(lambda x: x.replace(',',' '))
df['Composition'] = df['Composition'].apply(lambda x: x.replace(' ',''))
df['Composition'] = df['Composition'].apply(lambda x: x.replace("'",''))
df['Composition'] = df['Composition'].apply(lambda x: "".join(x.rstrip()))
df.head()

这样做会删除Composition列中文本中的所有空格,最终成为一个长字符串集。

df['Indexer'] = df['Composition'].factorize()[0]
#df['Indexer']
Indexer_dfmin = df[['Item',    'Indexer']].drop_duplicates().sort_values('Indexer')
df_to_Indexer = dict(Indexer_dfmin.values)
Indexer_to_df = dict(Indexer_dfmin[['Indexer', 'Item']].values)
#df['Composition'] = df['Composition'].str.split(",")
df.head()

Composition使用 pd.factorize() 对列进行了因式分解。

from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(sublinear_tf=True, norm='l2', encoding='latin-1', ngram_range=(1,8), analyzer='word',lowercase=True)
features = tfidf.fit_transform(dftest.Composition.values.astype('U')).toarray()
labels = dftest.Indexer
features.shape

使用sklearn RigdeClassifierCV我能够对数据进行建模并Item使用列的字符串预测名称Composition

from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.linear_model import RidgeClassifierCV
X_train, X_test, y_train, y_test = train_test_split(df['Composition'].values.astype('U'),df['Item'].values.astype('U'), random_state=42)
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(X_train)
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
clf = RidgeClassifierCV(alphas=[1e-3, 1e-2, 1e-1, 1]).fit(X_train_tfidf, y_train)

这种方法的问题:
1)模型没有学习Composition列中的单词并构建词汇表。
2)因此,如果我使用Composition列中带有空格的单词,模型将无法正确预测。
3)准确率可以接近100%,这意味着模型过拟合。

这就是为什么我说这不是一个聪明的解决方案。我想知道如何修复我的模型中的错误和问题。感谢一些专家对此的建议。请随意发表评论。提前致谢。