my-simple-ml / README.md
Coco-Spot's picture
Upload README.md with huggingface_hub
c64f5b3 verified
|
Raw
History Blame Contribute Delete
7.93 kB
---
language:
- en
- zh
tags:
- PyTorch
- Text Classification
- Sentiment Analysis
- GloVe
datasets:
- imdb
widget:
- text: "This movie was absolutely wonderful. The acting was great and the plot was engaging."
- text: "I hated this film. It was a complete waste of time."
---
[English](#english) | [简体中文](#chinese)
<a id="english"></a>
# Simple Sentiment Analysis NN with GloVe Embeddings
This is a PyTorch-based neural network model for binary sentiment classification (positive/negative) on the IMDB dataset.
## Model Description
The model was built as a lightweight Feed-Forward Neural Network that utilizes pre-trained GloVe embeddings for token representations. It performs average pooling over the embedded tokens of a sequence to create a sentence-level representation, which then passes through two linear layers to output a sentiment probability.
### Architecture
- **Tokenization:** Custom whitespace and punctuation tokenizer. Sequence length is padded/truncated to 150 tokens.
- **Embedding Layer:** Pre-trained weights loaded from a custom `tiny_glove.json` dictionary. The embedding layer is frozen during training.
- **Pooling:** Average pooling across the sequence dimension `[batch_size, max_len, embed_dim] -> [batch_size, embed_dim]`.
- **Fully Connected Network:**
- `Linear(embed_dim, 64)` + `ReLU()`
- `Linear(64, 1)` + `Sigmoid()`
## Training Data
The model was trained on a balanced subset of the IMDB movie reviews dataset containing 10,000 samples (`imdb_balanced_10k.csv`).
- **Train Split:** 8,000 samples (80%)
- **Test Split:** 2,000 samples (20%)
## Evaluation Results
- **Test Accuracy:** 0.6870 (68.7%)
## Training Parameters
- **Loss Function:** Binary Cross Entropy Loss (`BCELoss`)
- **Optimizer:** Adam
- **Learning Rate:** 0.001
- **Batch Size:** 64
- **Epochs:** 10
## Artifacts included
- `sentiment_nn.pth`: The PyTorch `state_dict` of the trained model.
- `vocab.pkl`: A serialized dictionary mapping string tokens to integer indices (includes `<PAD>` and `<UNK>` tokens).
- `label_encoder.pkl`: Scikit-learn LabelEncoder used to encode string labels to binary classes.
## How to use
```python
import torch
import torch.nn as nn
import joblib
import re
import string
import numpy as np
# Load Vocab and Label Encoder
vocab = joblib.load("vocab.pkl")
label_encoder = joblib.load("label_encoder.pkl")
embed_dim = 300 # Depends on the Glove embeddings used
# Recreate the PyTorch model
class SentimentNN(nn.Module):
def __init__(self, vocab_size, embed_dim):
super(SentimentNN, self).__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.fc1 = nn.Linear(embed_dim, 64)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(64, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
embeds = self.embedding(x)
out = embeds.mean(dim=1)
out = self.fc1(out)
out = self.relu(out)
out = self.fc2(out)
out = self.sigmoid(out)
return out
model = SentimentNN(len(vocab), embed_dim)
model.load_state_dict(torch.load("sentiment_nn.pth"), strict=False)
model.eval()
# Inference
MAX_LEN = 150
text = "This movie is amazing!"
text = str(text).lower()
text = re.sub(r'[' + string.punctuation + ']', ' ', text)
tokens = text.split()
indices = [vocab.get(t, 1) for t in tokens[:MAX_LEN]]
if len(indices) < MAX_LEN:
indices += [0] * (MAX_LEN - len(indices))
input_tensor = torch.tensor([indices], dtype=torch.long)
with torch.no_grad():
prediction = model(input_tensor).item()
# Get String Label
predicted_class = 1 if prediction > 0.5 else 0
print("Sentiment:", label_encoder.inverse_transform([predicted_class])[0])
print(f"Confidence: {prediction:.4f}")
```
---
<a id="chinese"></a>
# 基于 GloVe 词向量的简单情感分析神经网络
这是一个基于 PyTorch 构建的二分类情感分析(正向/负向)神经网络模型,在 IMDB 数据集上进行训练。
## 模型描述
该模型被设计为一个轻量级的前馈神经网络(Feed-Forward Neural Network),利用预训练的 GloVe 词向量作为 token 的嵌入表示。它通过对句子中所有 token 的嵌入向量进行平均池化(Average Pooling)来生成句子的全局特征表示,随后通过两个紧接的全连接线性层输出该句的情感概率预测。
### 模型架构
- **分词(Tokenization):** 自定义基于空格和标点符号截断的分词器。输入序列长度固定统一为 150 个 tokens(不足在末尾补长,超出则截断)。
- **嵌入层(Embedding Layer):** 初始化权重加载自项目中提供的 `tiny_glove.json` 预训练词向量文件字典。该层参数在训练期间冻结。
- **池化层(Pooling):** 在序列维度即单个句子的长度方向上进行全局平均池化:`[batch_size, max_len, embed_dim] -> [batch_size, embed_dim]`
- **全连接层(Fully Connected Network):**
- 第一层 `Linear(embed_dim, 64)` + `ReLU()`
- 第二层 `Linear(64, 1)` + `Sigmoid()` 激活函数输出最终概率。
## 训练数据
模型在一个内容分布平衡的 IMDB 电影评论高质量子集(包含 10,000 条样本数据,即项目中的 `imdb_balanced_10k.csv`)上完成训练。
- **训练集 (Train Split):** 8,000 条样本 (占比 80%)
- **测试集 (Test Split):** 2,000 条样本 (占比 20%)
## 评估结果 (Evaluation Results)
- **测试集准确率 (Test Accuracy):** 0.6870 (68.7%)
## 训练参数
- **损失函数(Loss Function):** 二元交叉熵损失函数 (`BCELoss`)
- **优化器(Optimizer):** Adam
- **学习率(Learning Rate):** 0.001
- **批大小(Batch Size):** 64
- **总轮数(Epochs):** 10
## 包含的文件
包含以下工作流自动生成的参数模型和必要的前置推理组件:
- `sentiment_nn.pth`: 训练完毕后的 PyTorch 网络模型 `state_dict` 权重字典。
- `vocab.pkl`: 一个映射字典,将文本中的 tokens 映射转化为具体的整型 ID(保留了包括 `<PAD>``<UNK>` 字段)。
- `label_encoder.pkl`: Scikit-learn 的 LabelEncoder 对象,用于预测通过后把二分类数值复原回原本的字符串文字标签。
## 如何使用
可以参考以下的 Python 推理模板逻辑将文本转为正确结果:
```python
import torch
import torch.nn as nn
import joblib
import re
import string
import numpy as np
# 加载词表和标签编码器
vocab = joblib.load("vocab.pkl")
label_encoder = joblib.load("label_encoder.pkl")
embed_dim = 300 # 需要与预训练词向量维度一致
# 重新声明 PyTorch 模型结构
class SentimentNN(nn.Module):
def __init__(self, vocab_size, embed_dim):
super(SentimentNN, self).__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.fc1 = nn.Linear(embed_dim, 64)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(64, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
embeds = self.embedding(x)
out = embeds.mean(dim=1)
out = self.fc1(out)
out = self.relu(out)
out = self.fc2(out)
out = self.sigmoid(out)
return out
model = SentimentNN(len(vocab), embed_dim)
model.load_state_dict(torch.load("sentiment_nn.pth"), strict=False)
model.eval()
# 推理预测
MAX_LEN = 150
text = "This movie is amazing!"
text = str(text).lower()
text = re.sub(r'[' + string.punctuation + ']', ' ', text)
tokens = text.split()
indices = [vocab.get(t, 1) for t in tokens[:MAX_LEN]]
if len(indices) < MAX_LEN:
indices += [0] * (MAX_LEN - len(indices))
input_tensor = torch.tensor([indices], dtype=torch.long)
with torch.no_grad():
prediction = model(input_tensor).item()
# 获取结果
predicted_class = 1 if prediction > 0.5 else 0
print("情感判定 (Sentiment):", label_encoder.inverse_transform([predicted_class])[0])
print(f"置信度 (Confidence): {prediction:.4f}")
```