Myers-Briggs2017性格数据集和SpaCy文本分类

摘要

合集:AI案例-NLP-人类生理
AI问题:文本分类
数据集:Myers-Briggs2017性格数据集
数据集价值:支持人类性格分析,帮助人们更好地了解自己和他人,促进个人成长和团队合作。
解决方案:SpaCy文本分类

一、问题描述

Myers-Briggs Type Indicator(MBTI)是一种流行的性格分类系统,由Katharine Cook Briggs和她的心理学家女儿Isabel Briggs Myers共同开发。MBTI基于瑞士精神病学家Carl Gustav Jung的理论,特别是他在其著作《心理类型》中提出的个性类型学。MBTI旨在帮助人们更好地了解自己和他人,促进个人成长和团队合作。Myers-Briggs Personality Type Dataset 最常见的版本由匿名用户发布在 Kaggle 上,发布时间为 2017年。

MBTI的四个维度

MBTI将人们的性格特征分为四个二元维度,每个维度有两个极端,形成八个极端类型:

  1. 外向(E)与内向(I)
    • 外向(E-Extroversion):能量来源于与他人的互动和外部世界。
    • 内向(I-Introversion):能量来源于内心的思考和独处。
  2. 感觉(S)与直觉(N)
    • 感觉(S-Sensing):依赖于直接的感官信息和现实的具体细节。
    • 直觉(N-Intuition):关注潜在的可能性、未来的趋势和抽象的概念。
  3. 思维(T)与情感(F)
    • 思维(T-Thinking):决策基于逻辑分析和客观事实。
    • 情感(F-Feeling):决策基于个人价值观和情感反应。
  4. 判断(J)与感知(P)
    • 判断(J-Judging):倾向于有序、计划和决定性的行为。
    • 感知(P-Perceiving):倾向于灵活、自发和开放的行为。

MBTI性格类型

MBTI (Myers Briggs Personality Type Indicator)性格分类系统根据以下四个维度:内向,直觉,思维和感知能力,将一个人个性分为16个不同的类型。我们可以根据他们在社交媒体上发布的帖子的类型来确定其个性。

每个维度上的两个极端组合起来,形成16种不同的性格类型,每种类型由四个字母表示,例如:

  • INTP:内向、直觉、思维、感知
  • ENFP:外向、直觉、情感、感知
  • ESTJ:外向、感觉、思维、判断
  • ISFJ:内向、感觉、情感、判断

例如,一个偏好内向、直觉、思考和知觉的人在性格分类系统中会被标记为INTP,而且有很多基于性格的组成部分可以模拟或描述这个人基于标签的偏好或行为。 它是世界上最受欢迎的性格测试之一,它在商业、在线、娱乐、研究等领域都有应用。简单的搜索就能揭示出这个测试随着时间的推移被使用的所有不同方式。可以说,这个测试在其使用方面在世界上仍然非常相关。 从科学或心理学的角度来看,它是基于Carl Jung对认知功能的研究。这是一个包含8种不同功能、思维过程或思维方式的模型,这些被认为存在于思维中。后来,这项工作被转化为几种不同的性格系统,使其更易于理解,其中最受欢迎的当然是MBTI。 最近,由于其周围的实验不可靠等原因,其有效性受到了质疑。但它仍然被视为在许多领域都非常有用的工具,而这个数据集的目的是帮助查看是否可以在特定类型及其写作风格中检测到任何模式,这总体上探索了该测试在分析、预测或分类行为方面的有效性。

MBTI的应用

  • 个人发展:帮助个人了解自己的性格优势和劣势,促进自我提升。
  • 职业指导:协助人们选择与自己性格类型相匹配的职业和工作环境。
  • 团队建设:增强团队成员之间的理解与合作,优化团队绩效。
  • 教育与培训:用于教育领域的学生性格评估和教学方法改进。

注意事项

尽管MBTI在许多领域得到了广泛应用,但它也有一些局限性:

  • MBTI是一种自我报告工具,结果可能受到个人主观性的影响。
  • MBTI的分类是相对固定的,但人的性格特征可能会随时间和环境变化。
  • MBTI不应被视为绝对的或决定性的性格描述,而应作为促进自我理解和人际沟通的工具。

总之,Myers-Briggs Type Indicator是一个有助于理解个体差异和促进人际和谐的有用工具。

二、数据集内容

数据结构

这个数据集包含超过8,600行的数据,一行数据对应一个人的信息:

  • 类型(4个字母的代码/类型)
  • 他们最近发布的50件事中的每一件的一个部分。每个条目由”|||”(3个竖线字符)分隔。

数据样例:

ENTJ    
'You're fired.|||
That's another silly misconception. That approaching is logically is going to be the key to unlocking whatever it is you think you are entitled to.   Nobody wants to be approached with BS...|||
But guys... he REALLY wants to go on a super-duper-long-ass vacation. C'mon guys. His boss just doesn't listen or get it. He even approached him logically and everything.|||
Never mind. Just go on permanent vacation.
...

数据集使用许可协议

Deed – CC0 1.0 Universal – Creative Commons

三、SpaCy和GPT区别

SpaCy 是一个流行的自然语言处理库,专为生产环境设计。它提供了许多功能,如分词、词性标注、命名实体识别、依存关系解析等。spaCy 还支持多种语言,并且具有高性能和易用性。SpaCy 这个名字来源于 “spacy” 这个词,意思是 “宽敞的” 。这个名字暗示了它能够处理大规模文本数据的能力。

核心功能

SpaCy 的核心功能包括:

  • 分词(Tokenization):将文本拆分成单词、标点符号等基本单元。
  • 词性标注(POS Tagging):识别单词的词性(名词、动词、形容词等)。
  • 依存句法分析(Dependency Parsing):分析句子中单词之间的语法关系。
  • 命名实体识别(Named Entity Recognition):识别文本中的人名、地名、组织名等实体。
  • 文本分类(Text Classification):对文本进行类别划分(如情感分析)。
  • 词向量(Word Vectors):提供预训练的词嵌入(如 GloVe、Word2Vec)。

工作流程

  1. 文本输入 → 分词(Tokenization) → 生成 Doc 对象(结构化文本)。
  2. 词性标注(POS Tagging) → 标注每个单词的词性。
  3. 依存句法分析(Dependency Parsing) → 构建句法树。
  4. 命名实体识别(NER命名实体识别) → 识别并分类实体(如人名、地名)。
  5. 可选任务(如文本分类、词向量计算)。

架构

SpaCy 的架构是 模块化 的,主要包括:

  1. Language 类(如 English, Chinese):
    • 管理 NLP 处理流程(Pipeline)。
    • 包含分词规则、词性标注模型等。
  2. Doc 对象:存储分词后的文本及其 NLP 属性(词性、依存关系等)。
  3. Token 对象:表示单个单词及其属性(词性、依存关系等)。
  4. Span 对象:表示文本片段(如命名实体)。
  5. Vocab 对象:存储词汇表、词向量等共享数据。
  6. 处理管道(Pipeline):由多个组件(如 tagger, parser, NER命名实体识别)组成,按顺序处理文本。

SpaCy 的模型

  • 统计模型(如 en_core_web_sm):
    • 基于 CNN(卷积神经网络) 或 Transformer(较新SpaCy版本)。
    • 预训练的词向量(如 GloVe)。
  • 规则引擎:用于分词、短语匹配(如 Matcher 类)。

SpaCy 和 GPT 的区别

特性SpaCyGPT(如 GPT-3/4)
主要用途NLP 任务(分词、NER命名实体识别、句法分析)文本生成、问答、对话
架构基于 CNN/Transformer(小型模型)基于 Transformer(超大规模)
训练方式监督学习(任务特定)自监督学习(海量文本预训练)
运行方式本地高效运行云端 API 或大模型本地部署
可定制性可训练小模型、规则增强微调(Fine-tuning)或 Prompt 工程
输出结构化 NLP 数据(如词性、实体)自然语言文本生成

关键区别

  1. 任务不同:
    • SpaCy 用于 NLP 结构化分析(如分词、NER命名实体识别)。
    • GPT 用于 生成自然语言(如写文章、聊天)。
  2. 模型规模:
    • SpaCy 的模型较小(通常几百 MB)。
    • GPT 的模型极大(如 GPT-3 有 1750 亿参数)。
  3. 运行环境:
    • SpaCy 可在本地 CPU/GPU 高效运行。
    • GPT 需要高性能 GPU/TPU 或云端服务。

总结

  • SpaCy 是一个 轻量级、高效的 NLP 库,适用于 结构化文本分析(如分词、NER命名实体识别)。
  • GPT 是一个 超大规模生成模型,适用于 文本生成、对话。
  • SpaCy 适合:需要快速 NLP 处理的场景(如信息提取)。本地化部署、低延迟应用。
  • GPT 适合:需要自然语言生成的场景(如聊天机器人)。依赖云端大模型能力的任务。

如果你需要 文本分析(如实体识别、句法分析),用 SpaCy;如果你需要 文本生成(如写作、问答),用 GPT。

四、文本性格分类

这是一个基于卷积神经网络CNN的文本分类器,它使用自然语言处理开发库spacy,并能够根据你撰写的文本或帖子来分类你的Myers-Briggs性格类型(例如INTJ,ENFP)。

安装SpaCy开发包

Thinc 是一个深度学习框架,专为 NLP 任务设计。它是 spaCy 的核心组件之一,提供了许多用于构建和训练神经网络模型的工具。Thinc 支持多种神经网络架构,如循环神经网络(RNN)、卷积神经网络(CNN)和变换器(Transformer)等。

conda create -n spacy python=3.12
conda activate spacy
conda install spacy
conda install -c conda-forge scikit-learn
conda install -c conda-forge pandas
conda install -c conda-forge matplotlib

conda list spacy

# packages in environment at D:\App-Data\conda3\envs\spacy:
#
# Name                   Version                   Build Channel
spacy                     3.8.2           py312h214f63a_0   anaconda
spacy-legacy             3.0.12         py312haa95532_0   anaconda
spacy-loggers             1.0.4           py312haa95532_0   anaconda

该环境使用spacy3.8.2。

spacy开发包依赖于深度神经网络框架thinc。

conda list thinc

# packages in environment at D:\App-Data\conda3\envs\spacy:
#
# Name                   Version                   Build Channel
thinc                     8.3.2           py312h214f63a_0   anaconda

该环境使用thinc3.8.2。

性格分类训练

源码:spacy-nlp.py

1、引入开发包和导入数据

import random
from pathlib import Path
import spacy
from spacy.util import minibatch, compounding
from spacy.training import Example
from sklearn.model_selection import train_test_split
import pandas as pd

df = pd.read_csv("mbti_1.csv")

2、main()函数初始化

参数:

  • model:如果传入了预训练模型的路径,则加载该模型,否则创建一个新的空白英语模型。
  • output_dir:指定训练后的模型保存路径。
  • n_iter:训练迭代次数,默认20次。
  • n_texts:指定训练数据的数量,默认2000。

如果传入了模型路径,则加载指定模型。否则,创建一个新的空白英文模型,便于从头开始训练。检查模型管道中是否包含多标签文本分类器 'textcat_multilabel'。如果没有,则添加该管道;如果已存在,则直接获取该管道。为文本分类器添加标签,用于多标签分类任务中的四种标签。使用 load_data 函数加载数据,并按照 n_texts 限制训练数据量。将训练数据转换成 spaCy 所需的格式。将文本和标签的列表转换成 Example 对象,这是 spaCy 3.x 及以上版本要求的数据格式。

函数功能:

  • 初始化模型(空白模型或加载预训练模型)
  • 添加/获取多标签文本分类器
  • 添加MBTI标签(INTROVERTED, INTUITIVE, JUDGEMENTAL, THINKING)
  • 加载并预处理数据
  • 训练模型并评估
  • 保存模型

训练模型:

禁用其他非文本分类的管道组件以提高训练效率。初始化优化器并执行训练循环。每一轮训练中:

  • 按批次大小(使用 compounding 动态调整)处理训练数据。
  • 更新模型,计算损失。
  • 使用 evaluate 函数在验证集上评估模型,输出损失/LOSS、精确率/P、召回率/R和 F1 分数。

使用训练好的模型对一个示例文本进行分类,并输出预测的标签。

def main(model=None, output_dir=None, n_iter=20, n_texts=2000):
  if model is not None:
      nlp = spacy.load(model)
      print("Loaded model '%s'" % model)
  else:
      nlp = spacy.blank('en')
      print("Created blank 'en' model")

  # Check if the 'textcat_multilabel' pipeline is already in the model, if not, add it
  if 'textcat_multilabel' not in nlp.pipe_names:
      textcat = nlp.add_pipe('textcat_multilabel', last=True)
  else:
      textcat = nlp.get_pipe('textcat_multilabel')

  # Add labels to the text classifier
  textcat.add_label('INTROVERTED')
  textcat.add_label('INTUITIVE')
  textcat.add_label('JUDGEMENTAL')
  textcat.add_label('THINKING')

  print("Loading MBTI data...")
  (train_texts, train_cats), (dev_texts, dev_cats) = load_data(df, limit=n_texts)
  print("Using {} examples ({} training, {} evaluation)"
        .format(n_texts, len(train_texts), len(dev_texts)))
  train_data = list(zip(train_texts, [{'cats': cats} for cats in train_cats]))

  # Convert texts and annotations to Example objects
  train_data = [Example.from_dict(nlp.make_doc(text), annotation) for text, annotation in train_data]

  # Disable other pipes for training
  other_pipes = [pipe for pipe in nlp.pipe_names if pipe != 'textcat_multilabel']
  with nlp.disable_pipes(*other_pipes):
      optimizer = nlp.initialize()
      print("Training the model...")
      print('{:^5}\t{:^5}\t{:^5}\t{:^5}'.format('LOSS', 'P', 'R', 'F'))
      for i in range(n_iter):
          losses = {}
          batches = minibatch(train_data, size=compounding(4., 32., 1.001))
          for batch in batches:
              nlp.update(batch, sgd=optimizer, drop=0.2, losses=losses)
          # with textcat.model.use_params(optimizer.averages):
          #     scores = evaluate(nlp.tokenizer, textcat, dev_texts, dev_cats)
          # 直接调用evaluate函数
          scores = evaluate(nlp.tokenizer, textcat, dev_texts, dev_cats)            
          print('{0:.3f}\t{1:.3f}\t{2:.3f}\t{3:.3f}'
                .format(losses['textcat_multilabel'], scores['textcat_p'],
                        scores['textcat_r'], scores['textcat_f']))

  test_text = "This movie sucked"
  doc = nlp(test_text)
  print(test_text, doc.cats)

  if output_dir is not None:
      output_dir = Path(output_dir)
      if not output_dir.exists():
          output_dir.mkdir()
      nlp.to_disk(output_dir)
      print("Saved model to", output_dir)

      print("Loading from", output_dir)
      nlp2 = spacy.load(output_dir)
      doc2 = nlp2(test_text)
      print(test_text, doc2.cats)

3、加载数据

  • 从DataFrame中获取MBTI类型(type)和帖子内容(posts)
  • 将MBTI类型转换为四个二元标签:
    • INTROVERTED: 第一个字母是’I'(内向)还是’E'(外向)
    • INTUITIVE: 第二个字母是’N'(直觉)还是’S'(实感)
    • THINKING: 第三个字母是’T'(思考)还是’F'(情感)
    • JUDGEMENTAL: 第四个字母是’J'(判断)还是’P'(知觉)
  • 使用train_test_split分割数据(默认80%训练,20%测试)
def load_data(train_data, limit=0, split=0.8):
  train_data = train_data[-limit:]
  Y, X = train_data["type"], train_data["posts"]
  y = []
  for y_ in Y:
      INTROVERTED = y_[0] == 'I'
      INTUITIVE = y_[1] == 'N'
      THINKING = y_[2] == 'T'
      JUDGEMENTAL = y_[3] == 'J'
      y.append({'INTROVERTED': INTROVERTED, "INTUITIVE": INTUITIVE, "THINKING": THINKING, "JUDGEMENTAL": JUDGEMENTAL})

  X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=split, random_state=42)
  return (X_train, y_train), (X_test, y_test)

4、评估函数

参数:

  • tokenizer:用于将输入文本转为 spaCyDoc 对象的分词器。
  • textcat:已训练的多标签文本分类器。
  • texts:需要进行评估的文本列表。
  • cats:每个文本的标签,格式为 [{label1: True/False, label2: True/False, ...}]

初始化评估变量:定义真阳性 (tp)、假阳性 (fp)、假阴性 (fn) 和真阴性 (tn) 的初始值为 1e-8,以避免后续出现除以零的错误。

遍历预测结果并更新评估指标:

使用 textcat.pipe 批量处理生成器中的 docs,提升效率。

对于每个预测 doc,根据 doc.cats 的预测分数和 cats 中的真实标签逐一比较各标签:

  • 真阳性 (tp):预测为正,且真实值为正(即 score >= 0.5gold[label] >= 0.5)。
  • 假阳性 (fp):预测为正,真实值为负(即 score >= 0.5gold[label] < 0.5)。
  • 真阴性 (tn):预测为负,真实值为负(即 score < 0.5gold[label] < 0.5)。
  • 假阴性 (fn):预测为负,真实值为正(即 score < 0.5gold[label] >= 0.5)。

计算精确率、召回率和 F1 分数:

  • 精确率 (Precision):预测为正的标签中,实际为正的比例。
  • 召回率 (Recall):真实为正的标签中,成功预测为正的比例。
  • F1 分数:精确率和召回率的调和平均,衡量模型的综合表现。

函数返回:返回一个字典,包含精确率、召回率和 F1 分数。

def evaluate(tokenizer, textcat, texts, cats):
  docs = (tokenizer(text) for text in texts)
  tp = 1e-8
  fp = 1e-8
  fn = 1e-8
  tn = 1e-8
  for i, doc in enumerate(textcat.pipe(docs)):
      gold = cats[i]
      for label, score in doc.cats.items():
          if label not in gold:
              continue
          if score >= 0.5 and gold[label] >= 0.5:
              tp += 1.
          elif score >= 0.5 and gold[label] < 0.5:
              fp += 1.
          elif score < 0.5 and gold[label] < 0.5:
              tn += 1
          elif score < 0.5 and gold[label] >= 0.5:
              fn += 1
  precision = tp / (tp + fp)
  recall = tp / (tp + fn)
  f_score = 2 * (precision * recall) / (precision + recall)
  return {'textcat_p': precision, 'textcat_r': recall, 'textcat_f': f_score}

main(output_dir="./model")

运行结果

(spacy) C:\AiSelect1\NLP\code\MBTI>python spacy-nlp.py
Created blank 'en' model
Loading MBTI data...
Using 2000 examples (400 training, 1600 evaluation)
Training the model...
LOSS     P       R       F
24.756 0.814   0.682   0.742
20.862 0.830   0.655   0.732
17.936 0.795   0.852   0.822
13.319 0.870   0.756   0.809
10.880 0.852   0.804   0.827
7.997   0.861   0.836   0.849
6.945   0.875   0.823   0.848
5.443   0.865   0.837   0.851
4.701   0.863   0.863   0.863
3.822   0.880   0.830   0.855
3.100   0.881   0.829   0.854
2.681   0.882   0.810   0.845
2.009   0.876   0.840   0.858
1.741   0.890   0.798   0.842
1.882   0.892   0.786   0.835
1.712   0.878   0.816   0.846
2.116   0.887   0.801   0.842
1.588   0.875   0.835   0.854
1.379   0.898   0.795   0.843
0.931   0.877   0.812   0.843
This movie sucked {'INTROVERTED': 0.030510596930980682, 'INTUITIVE': 0.3276093304157257, 'JUDGEMENTAL': 0.38206788897514343, 'THINKING': 0.9431203007698059}
Saved model to model
Loading from model
This movie sucked {'INTROVERTED': 0.030510596930980682, 'INTUITIVE': 0.3276093304157257, 'JUDGEMENTAL': 0.38206788897514343, 'THINKING': 0.9431203007698059}

对于文本:This movie sucked(这部电影很烂)。INTROVERTED/内向性格概率为:0.03;INTUITIVE/直觉性格概率为:0.32;JUDGEMENTAL/爱评判性格概率为:0.38;THINKING/爱思考性格的概率为:0.94。

四、参考资料

SpaCy,一个高效的自然语言处理库!

五、获取案例套件

六、获取案例套装

需要登录后才允许下载文件包。登录

发表评论