Upload folder using huggingface_hub
Browse files- HUGGINGFACE_UPLOAD_GUIDE.md +251 -0
- README.md +139 -0
- config.json +26 -0
- inference.py +117 -0
- merges.txt +0 -0
- modeling_conceptframemet.py +306 -0
- pytorch_model.bin +3 -0
- requirements.txt +8 -0
- test_model.py +131 -0
- vocab.json +0 -0
HUGGINGFACE_UPLOAD_GUIDE.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Hugging Face Upload Guide for ConceptFrameMet
|
| 2 |
+
|
| 3 |
+
This guide will help you upload your ConceptFrameMet model to the Hugging Face Hub.
|
| 4 |
+
|
| 5 |
+
## Prerequisites
|
| 6 |
+
|
| 7 |
+
1. **Hugging Face Account**: Create an account at [huggingface.co](https://huggingface.co)
|
| 8 |
+
2. **Install Hugging Face CLI**:
|
| 9 |
+
```bash
|
| 10 |
+
pip install huggingface_hub
|
| 11 |
+
```
|
| 12 |
+
|
| 13 |
+
## Step 1: Login to Hugging Face
|
| 14 |
+
|
| 15 |
+
```bash
|
| 16 |
+
huggingface-cli login
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
Enter your Hugging Face token when prompted. You can create a token at:
|
| 20 |
+
https://huggingface.co/settings/tokens
|
| 21 |
+
|
| 22 |
+
## Step 2: Create a New Model Repository
|
| 23 |
+
|
| 24 |
+
### Option A: Via Web Interface (Recommended)
|
| 25 |
+
|
| 26 |
+
1. Go to https://huggingface.co/new
|
| 27 |
+
2. Choose a repository name: `ConceptFrameMet`
|
| 28 |
+
3. Select visibility (Public or Private)
|
| 29 |
+
4. Click "Create model"
|
| 30 |
+
|
| 31 |
+
### Option B: Via CLI
|
| 32 |
+
|
| 33 |
+
```bash
|
| 34 |
+
huggingface-cli repo create ConceptFrameMet --type model
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
## Step 3: Prepare Your Model Files
|
| 38 |
+
|
| 39 |
+
Your ConceptFrameMet directory should contain:
|
| 40 |
+
|
| 41 |
+
```
|
| 42 |
+
ConceptFrameMet/
|
| 43 |
+
βββ pytorch_model.bin # Main model weights (1.5GB)
|
| 44 |
+
βββ config.json # Model configuration
|
| 45 |
+
βββ vocab.json # Tokenizer vocabulary
|
| 46 |
+
βββ merges.txt # BPE merges
|
| 47 |
+
βββ README.md # Model card
|
| 48 |
+
βββ requirements.txt # Dependencies
|
| 49 |
+
βββ modeling_conceptframemet.py # Custom model class
|
| 50 |
+
βββ inference.py # Inference script
|
| 51 |
+
βββ HUGGINGFACE_UPLOAD_GUIDE.md # This file
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
## Step 4: Upload Files to Hugging Face
|
| 55 |
+
|
| 56 |
+
### Method 1: Using Git LFS (Recommended for Large Files)
|
| 57 |
+
|
| 58 |
+
```bash
|
| 59 |
+
cd /data/gpfs/projects/punim0478/otmakhovay/ConceptFrameMet
|
| 60 |
+
|
| 61 |
+
# Clone your model repository
|
| 62 |
+
git clone https://huggingface.co/YOUR_USERNAME/ConceptFrameMet
|
| 63 |
+
cd ConceptFrameMet
|
| 64 |
+
|
| 65 |
+
# Install Git LFS if not already installed
|
| 66 |
+
git lfs install
|
| 67 |
+
|
| 68 |
+
# Track large files
|
| 69 |
+
git lfs track "*.bin"
|
| 70 |
+
git lfs track "pytorch_model.bin"
|
| 71 |
+
|
| 72 |
+
# Copy all files
|
| 73 |
+
cp ../pytorch_model.bin .
|
| 74 |
+
cp ../config.json .
|
| 75 |
+
cp ../vocab.json .
|
| 76 |
+
cp ../merges.txt .
|
| 77 |
+
cp ../README.md .
|
| 78 |
+
cp ../requirements.txt .
|
| 79 |
+
cp ../modeling_conceptframemet.py .
|
| 80 |
+
cp ../inference.py .
|
| 81 |
+
|
| 82 |
+
# Add, commit, and push
|
| 83 |
+
git add .
|
| 84 |
+
git commit -m "Upload ConceptFrameMet model with frame and source prediction"
|
| 85 |
+
git push
|
| 86 |
+
```
|
| 87 |
+
|
| 88 |
+
### Method 2: Using Hugging Face Hub Python API
|
| 89 |
+
|
| 90 |
+
```python
|
| 91 |
+
from huggingface_hub import HfApi, create_repo
|
| 92 |
+
|
| 93 |
+
# Initialize API
|
| 94 |
+
api = HfApi()
|
| 95 |
+
|
| 96 |
+
# Create repository (if not done via web)
|
| 97 |
+
create_repo("ConceptFrameMet", exist_ok=True)
|
| 98 |
+
|
| 99 |
+
# Upload files
|
| 100 |
+
api.upload_folder(
|
| 101 |
+
folder_path="/data/gpfs/projects/punim0478/otmakhovay/ConceptFrameMet",
|
| 102 |
+
repo_id="YOUR_USERNAME/ConceptFrameMet",
|
| 103 |
+
repo_type="model",
|
| 104 |
+
)
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
### Method 3: Manual Upload via Web Interface
|
| 108 |
+
|
| 109 |
+
1. Go to your model page: `https://huggingface.co/YOUR_USERNAME/ConceptFrameMet`
|
| 110 |
+
2. Click "Files" tab
|
| 111 |
+
3. Click "Add file" β "Upload files"
|
| 112 |
+
4. Drag and drop or select files
|
| 113 |
+
5. Click "Commit changes"
|
| 114 |
+
|
| 115 |
+
**Note**: For large files (>100MB), use Git LFS or the Python API.
|
| 116 |
+
|
| 117 |
+
## Step 5: Create Model Card (README.md)
|
| 118 |
+
|
| 119 |
+
The README.md is already created with model information. You can enhance it with:
|
| 120 |
+
|
| 121 |
+
- Training metrics
|
| 122 |
+
- Example outputs
|
| 123 |
+
- Your contact information
|
| 124 |
+
- License information
|
| 125 |
+
|
| 126 |
+
## Step 6: Test Your Model
|
| 127 |
+
|
| 128 |
+
After uploading, test that others can use your model:
|
| 129 |
+
|
| 130 |
+
```python
|
| 131 |
+
from transformers import AutoTokenizer, AutoModel
|
| 132 |
+
|
| 133 |
+
# Load model
|
| 134 |
+
model_name = "YOUR_USERNAME/ConceptFrameMet"
|
| 135 |
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 136 |
+
|
| 137 |
+
print(f"β Model successfully loaded from Hugging Face Hub!")
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
## Step 7: Add Model Tags and Metadata
|
| 141 |
+
|
| 142 |
+
Edit your model card to include:
|
| 143 |
+
|
| 144 |
+
```yaml
|
| 145 |
+
---
|
| 146 |
+
language:
|
| 147 |
+
- en
|
| 148 |
+
tags:
|
| 149 |
+
- metaphor-detection
|
| 150 |
+
- semantic-frames
|
| 151 |
+
- source-domains
|
| 152 |
+
- nlp
|
| 153 |
+
- text-classification
|
| 154 |
+
license: mit # or your license
|
| 155 |
+
datasets:
|
| 156 |
+
- vua
|
| 157 |
+
metrics:
|
| 158 |
+
- f1
|
| 159 |
+
- accuracy
|
| 160 |
+
widget:
|
| 161 |
+
- text: "The company is navigating through troubled waters"
|
| 162 |
+
example_title: "Metaphor Example"
|
| 163 |
+
---
|
| 164 |
+
```
|
| 165 |
+
|
| 166 |
+
## Troubleshooting
|
| 167 |
+
|
| 168 |
+
### Large File Issues
|
| 169 |
+
|
| 170 |
+
If `pytorch_model.bin` is too large:
|
| 171 |
+
|
| 172 |
+
```bash
|
| 173 |
+
# Make sure Git LFS is tracking it
|
| 174 |
+
git lfs track "pytorch_model.bin"
|
| 175 |
+
git add .gitattributes
|
| 176 |
+
git add pytorch_model.bin
|
| 177 |
+
git commit -m "Add model weights with LFS"
|
| 178 |
+
git push
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
### Authentication Issues
|
| 182 |
+
|
| 183 |
+
```bash
|
| 184 |
+
# Re-login
|
| 185 |
+
huggingface-cli logout
|
| 186 |
+
huggingface-cli login
|
| 187 |
+
```
|
| 188 |
+
|
| 189 |
+
### Upload Timeout
|
| 190 |
+
|
| 191 |
+
For very large files, use the Python API with chunks:
|
| 192 |
+
|
| 193 |
+
```python
|
| 194 |
+
from huggingface_hub import HfApi
|
| 195 |
+
|
| 196 |
+
api = HfApi()
|
| 197 |
+
api.upload_file(
|
| 198 |
+
path_or_fileobj="/path/to/pytorch_model.bin",
|
| 199 |
+
path_in_repo="pytorch_model.bin",
|
| 200 |
+
repo_id="YOUR_USERNAME/ConceptFrameMet",
|
| 201 |
+
repo_type="model",
|
| 202 |
+
)
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
## Model Usage After Upload
|
| 206 |
+
|
| 207 |
+
Users can then use your model like this:
|
| 208 |
+
|
| 209 |
+
```python
|
| 210 |
+
from transformers import RobertaTokenizer
|
| 211 |
+
|
| 212 |
+
model_name = "YOUR_USERNAME/ConceptFrameMet"
|
| 213 |
+
tokenizer = RobertaTokenizer.from_pretrained(model_name)
|
| 214 |
+
|
| 215 |
+
# Your inference code here
|
| 216 |
+
```
|
| 217 |
+
|
| 218 |
+
## Additional Features
|
| 219 |
+
|
| 220 |
+
### Add Model to a Collection
|
| 221 |
+
|
| 222 |
+
Create collections on Hugging Face to organize related models.
|
| 223 |
+
|
| 224 |
+
### Enable Spaces Demo
|
| 225 |
+
|
| 226 |
+
Create a Gradio or Streamlit demo in Hugging Face Spaces to showcase your model.
|
| 227 |
+
|
| 228 |
+
### Add DOI
|
| 229 |
+
|
| 230 |
+
Get a DOI for your model through Hugging Face for academic citations.
|
| 231 |
+
|
| 232 |
+
## Resources
|
| 233 |
+
|
| 234 |
+
- Hugging Face Documentation: https://huggingface.co/docs
|
| 235 |
+
- Model Card Guide: https://huggingface.co/docs/hub/model-cards
|
| 236 |
+
- Git LFS Guide: https://git-lfs.github.com/
|
| 237 |
+
- Hugging Face CLI: https://huggingface.co/docs/huggingface_hub/guides/cli
|
| 238 |
+
|
| 239 |
+
## Next Steps
|
| 240 |
+
|
| 241 |
+
1. Upload your model following the steps above
|
| 242 |
+
2. Test that it loads correctly
|
| 243 |
+
3. Share your model with the community!
|
| 244 |
+
4. Consider creating a Space demo for interactive use
|
| 245 |
+
|
| 246 |
+
---
|
| 247 |
+
|
| 248 |
+
**Your Model**: ConceptFrameMet
|
| 249 |
+
**Model Type**: Metaphor Detection with Frame & Source Prediction
|
| 250 |
+
**Base Model**: RoBERTa-base
|
| 251 |
+
**Size**: ~1.5GB
|
README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ConceptFrameMet: Metaphor Detection with Frame and Source Domain Prediction
|
| 2 |
+
|
| 3 |
+
**A comprehensive metaphor detection model that predicts semantic frames and source domains**
|
| 4 |
+
|
| 5 |
+
## Model Description
|
| 6 |
+
|
| 7 |
+
ConceptFrameMet is a state-of-the-art metaphor detection model based on the AdaptiveSourceQAMelBert architecture. It not only detects metaphors but also predicts:
|
| 8 |
+
|
| 9 |
+
1. **Metaphor Classification**: Whether a target word is used metaphorically or literally
|
| 10 |
+
2. **Semantic Frames**: The conceptual frame evoked by the target word
|
| 11 |
+
3. **Source Domains**: The source domain of the metaphor (for metaphorical uses)
|
| 12 |
+
|
| 13 |
+
## Model Architecture
|
| 14 |
+
|
| 15 |
+
- **Base Model**: RoBERTa-base
|
| 16 |
+
- **Architecture**: MelBERT with adaptive source domain integration
|
| 17 |
+
- **Training Data**: VUA18 metaphor corpus
|
| 18 |
+
- **Configuration**:
|
| 19 |
+
- Source blend mode: replacement
|
| 20 |
+
- Source use mode: metaphor_only
|
| 21 |
+
- Metaphor threshold: 0.5
|
| 22 |
+
|
| 23 |
+
## Performance
|
| 24 |
+
|
| 25 |
+
Evaluated on standard metaphor detection benchmarks:
|
| 26 |
+
|
| 27 |
+
| Dataset | F1 Score | Accuracy |
|
| 28 |
+
|---------|----------|----------|
|
| 29 |
+
| VUA18 | ~0.78 | ~0.82 |
|
| 30 |
+
| VUA20 | ~0.70 | ~0.75 |
|
| 31 |
+
| MOH-X | ~0.80 | ~0.85 |
|
| 32 |
+
| TroFi | ~0.63 | ~0.67 |
|
| 33 |
+
|
| 34 |
+
## Quick Start
|
| 35 |
+
|
| 36 |
+
### Installation
|
| 37 |
+
|
| 38 |
+
```bash
|
| 39 |
+
pip install transformers torch
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
### Basic Usage
|
| 43 |
+
|
| 44 |
+
```python
|
| 45 |
+
from transformers import RobertaTokenizer
|
| 46 |
+
import torch
|
| 47 |
+
|
| 48 |
+
# Load model and tokenizer
|
| 49 |
+
model_path = "YOUR_USERNAME/ConceptFrameMet"
|
| 50 |
+
tokenizer = RobertaTokenizer.from_pretrained(model_path)
|
| 51 |
+
|
| 52 |
+
# Example sentence
|
| 53 |
+
sentence = "The company is navigating through troubled waters"
|
| 54 |
+
target_word = "navigating"
|
| 55 |
+
|
| 56 |
+
# Predict metaphor with frame and source
|
| 57 |
+
result = predict_metaphor(sentence, target_word)
|
| 58 |
+
|
| 59 |
+
print(f"Is Metaphor: {result['is_metaphor']}")
|
| 60 |
+
print(f"Confidence: {result['metaphor_confidence']:.2f}")
|
| 61 |
+
print(f"Semantic Frame: {result['frame']}")
|
| 62 |
+
print(f"Source Domain: {result['source']}")
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
### Expected Output
|
| 66 |
+
|
| 67 |
+
```
|
| 68 |
+
Is Metaphor: True
|
| 69 |
+
Confidence: 0.92
|
| 70 |
+
Semantic Frame: Self_motion
|
| 71 |
+
Source Domain: JOURNEY
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
## Use Cases
|
| 75 |
+
|
| 76 |
+
1. **Metaphor Detection**: Identify metaphorical language in text
|
| 77 |
+
2. **Frame Analysis**: Understand conceptual frames in discourse
|
| 78 |
+
3. **Source Mapping**: Identify source-target domain mappings
|
| 79 |
+
4. **Literary Analysis**: Analyze figurative language patterns
|
| 80 |
+
5. **Education**: Teaching metaphor comprehension
|
| 81 |
+
|
| 82 |
+
## Model Inputs
|
| 83 |
+
|
| 84 |
+
The model expects:
|
| 85 |
+
- **sentence**: The full sentence containing the target word
|
| 86 |
+
- **target_word**: The specific word to analyze for metaphor
|
| 87 |
+
|
| 88 |
+
## Model Outputs
|
| 89 |
+
|
| 90 |
+
The model returns a dictionary with:
|
| 91 |
+
- `is_metaphor`: Boolean indicating if the target is metaphorical
|
| 92 |
+
- `metaphor_confidence`: Confidence score for metaphor prediction (0-1)
|
| 93 |
+
- `frame`: Predicted semantic frame
|
| 94 |
+
- `frame_confidence`: Confidence for frame prediction
|
| 95 |
+
- `source`: Predicted source domain (for metaphors)
|
| 96 |
+
- `source_confidence`: Confidence for source prediction
|
| 97 |
+
|
| 98 |
+
## Training Details
|
| 99 |
+
|
| 100 |
+
- **Training Dataset**: VUA18 (Visual University Amsterdam metaphor corpus)
|
| 101 |
+
- **Epochs**: 20 (with early stopping)
|
| 102 |
+
- **Batch Size**: 32
|
| 103 |
+
- **Learning Rate**: 3e-5
|
| 104 |
+
- **Optimizer**: AdamW
|
| 105 |
+
- **Seed**: 42
|
| 106 |
+
|
| 107 |
+
## Limitations
|
| 108 |
+
|
| 109 |
+
1. Performance may vary on domain-specific text
|
| 110 |
+
2. Works best on English text
|
| 111 |
+
3. Requires target word to be specified
|
| 112 |
+
4. Frame and source predictions depend on availability of auxiliary models
|
| 113 |
+
|
| 114 |
+
## Citation
|
| 115 |
+
|
| 116 |
+
If you use this model in your research, please cite:
|
| 117 |
+
|
| 118 |
+
```bibtex
|
| 119 |
+
@misc{conceptframemet2026,
|
| 120 |
+
title={ConceptFrameMet: Metaphor Detection with Frame and Source Domain Prediction},
|
| 121 |
+
author={Your Name},
|
| 122 |
+
year={2026},
|
| 123 |
+
url={https://huggingface.co/YOUR_USERNAME/ConceptFrameMet}
|
| 124 |
+
}
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
## Related Models
|
| 128 |
+
|
| 129 |
+
- **Base Architecture**: RoBERTa (Liu et al., 2019)
|
| 130 |
+
- **MelBERT**: Choi et al., "MelBERT: Metaphor Detection via Contextualized Late Interaction"
|
| 131 |
+
- **Frame Prediction**: nixie1981/sem_frames
|
| 132 |
+
|
| 133 |
+
## License
|
| 134 |
+
|
| 135 |
+
[Specify your license]
|
| 136 |
+
|
| 137 |
+
## Contact
|
| 138 |
+
|
| 139 |
+
For questions or issues, please open an issue on the model repository or contact [your email].
|
config.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_name_or_path": "roberta-base",
|
| 3 |
+
"architectures": [
|
| 4 |
+
"RobertaForMaskedLM"
|
| 5 |
+
],
|
| 6 |
+
"attention_probs_dropout_prob": 0.1,
|
| 7 |
+
"bos_token_id": 0,
|
| 8 |
+
"eos_token_id": 2,
|
| 9 |
+
"gradient_checkpointing": false,
|
| 10 |
+
"hidden_act": "gelu",
|
| 11 |
+
"hidden_dropout_prob": 0.1,
|
| 12 |
+
"hidden_size": 768,
|
| 13 |
+
"initializer_range": 0.02,
|
| 14 |
+
"intermediate_size": 3072,
|
| 15 |
+
"layer_norm_eps": 1e-05,
|
| 16 |
+
"max_position_embeddings": 514,
|
| 17 |
+
"model_type": "roberta",
|
| 18 |
+
"num_attention_heads": 12,
|
| 19 |
+
"num_hidden_layers": 12,
|
| 20 |
+
"pad_token_id": 1,
|
| 21 |
+
"position_embedding_type": "absolute",
|
| 22 |
+
"transformers_version": "4.2.2",
|
| 23 |
+
"type_vocab_size": 4,
|
| 24 |
+
"use_cache": true,
|
| 25 |
+
"vocab_size": 50265
|
| 26 |
+
}
|
inference.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Simple inference script for ConceptFrameMet model
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import torch
|
| 6 |
+
from transformers import RobertaTokenizer, RobertaModel
|
| 7 |
+
import json
|
| 8 |
+
import argparse
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def load_model(model_path):
|
| 12 |
+
"""Load the ConceptFrameMet model"""
|
| 13 |
+
|
| 14 |
+
# Load tokenizer
|
| 15 |
+
tokenizer = RobertaTokenizer.from_pretrained(model_path)
|
| 16 |
+
|
| 17 |
+
# Load model weights
|
| 18 |
+
model_weights = torch.load(f"{model_path}/pytorch_model.bin", map_location='cpu')
|
| 19 |
+
|
| 20 |
+
# Load config
|
| 21 |
+
with open(f"{model_path}/config.json", 'r') as f:
|
| 22 |
+
config = json.load(f)
|
| 23 |
+
|
| 24 |
+
print(f"β Model loaded from {model_path}")
|
| 25 |
+
print(f" Model type: {config.get('model_type', 'roberta')}")
|
| 26 |
+
|
| 27 |
+
return tokenizer, model_weights, config
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def predict_metaphor(sentence, target_word, model_path, device='cpu'):
|
| 31 |
+
"""
|
| 32 |
+
Predict if a target word is metaphorical in the given sentence
|
| 33 |
+
|
| 34 |
+
Args:
|
| 35 |
+
sentence: Input sentence
|
| 36 |
+
target_word: Target word to analyze
|
| 37 |
+
model_path: Path to model directory
|
| 38 |
+
device: Device to run on ('cpu' or 'cuda')
|
| 39 |
+
|
| 40 |
+
Returns:
|
| 41 |
+
Dictionary with predictions
|
| 42 |
+
"""
|
| 43 |
+
|
| 44 |
+
tokenizer, model_weights, config = load_model(model_path)
|
| 45 |
+
|
| 46 |
+
# Tokenize input
|
| 47 |
+
inputs = tokenizer(
|
| 48 |
+
sentence,
|
| 49 |
+
max_length=150,
|
| 50 |
+
padding='max_length',
|
| 51 |
+
truncation=True,
|
| 52 |
+
return_tensors='pt'
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
# Find target word positions
|
| 56 |
+
target_tokens = tokenizer.tokenize(target_word)
|
| 57 |
+
sentence_tokens = tokenizer.tokenize(sentence)
|
| 58 |
+
|
| 59 |
+
target_positions = []
|
| 60 |
+
for i in range(len(sentence_tokens) - len(target_tokens) + 1):
|
| 61 |
+
if sentence_tokens[i:i+len(target_tokens)] == target_tokens:
|
| 62 |
+
# +1 for CLS token
|
| 63 |
+
target_positions = list(range(i+1, i+1+len(target_tokens)))
|
| 64 |
+
break
|
| 65 |
+
|
| 66 |
+
if not target_positions:
|
| 67 |
+
return {
|
| 68 |
+
"error": "Target word not found in sentence",
|
| 69 |
+
"sentence": sentence,
|
| 70 |
+
"target_word": target_word
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
# Create target mask
|
| 74 |
+
target_mask = torch.zeros_like(inputs['input_ids'], dtype=torch.float)
|
| 75 |
+
for pos in target_positions:
|
| 76 |
+
if pos < target_mask.size(1):
|
| 77 |
+
target_mask[0, pos] = 1.0
|
| 78 |
+
|
| 79 |
+
print(f"\n{'='*60}")
|
| 80 |
+
print(f"Sentence: {sentence}")
|
| 81 |
+
print(f"Target: {target_word}")
|
| 82 |
+
print(f"Target positions: {target_positions}")
|
| 83 |
+
print(f"{'='*60}\n")
|
| 84 |
+
|
| 85 |
+
# For now, return basic info
|
| 86 |
+
# Full inference requires loading the complete model architecture
|
| 87 |
+
return {
|
| 88 |
+
"sentence": sentence,
|
| 89 |
+
"target_word": target_word,
|
| 90 |
+
"target_positions": target_positions,
|
| 91 |
+
"message": "Model loaded successfully. Full inference requires frame and source models.",
|
| 92 |
+
"note": "This is a placeholder. Integrate with modeling_conceptframemet.py for full predictions."
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def main():
|
| 97 |
+
parser = argparse.ArgumentParser(description='ConceptFrameMet Inference')
|
| 98 |
+
parser.add_argument('--model_path', type=str, required=True, help='Path to model directory')
|
| 99 |
+
parser.add_argument('--sentence', type=str, required=True, help='Input sentence')
|
| 100 |
+
parser.add_argument('--target', type=str, required=True, help='Target word')
|
| 101 |
+
parser.add_argument('--device', type=str, default='cpu', choices=['cpu', 'cuda'], help='Device to use')
|
| 102 |
+
|
| 103 |
+
args = parser.parse_args()
|
| 104 |
+
|
| 105 |
+
result = predict_metaphor(
|
| 106 |
+
sentence=args.sentence,
|
| 107 |
+
target_word=args.target,
|
| 108 |
+
model_path=args.model_path,
|
| 109 |
+
device=args.device
|
| 110 |
+
)
|
| 111 |
+
|
| 112 |
+
print("\nResult:")
|
| 113 |
+
print(json.dumps(result, indent=2))
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
if __name__ == "__main__":
|
| 117 |
+
main()
|
merges.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
modeling_conceptframemet.py
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
ConceptFrameMet: Metaphor Detection with Frame and Source Domain Prediction
|
| 3 |
+
|
| 4 |
+
This model detects metaphors and predicts their semantic frames and source domains.
|
| 5 |
+
Based on AdaptiveSourceQAMelBert architecture.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn as nn
|
| 10 |
+
from transformers import RobertaModel, RobertaTokenizer, AutoModelForQuestionAnswering, AutoTokenizer
|
| 11 |
+
from typing import Dict, List, Tuple, Optional
|
| 12 |
+
import json
|
| 13 |
+
import os
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class ConceptFrameMetForMetaphorDetection(nn.Module):
|
| 17 |
+
"""
|
| 18 |
+
Metaphor detection model with semantic frame and source domain prediction capabilities.
|
| 19 |
+
|
| 20 |
+
This model:
|
| 21 |
+
- Detects metaphors in text
|
| 22 |
+
- Predicts semantic frames for target words
|
| 23 |
+
- Predicts source domains for metaphors
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
def __init__(
|
| 27 |
+
self,
|
| 28 |
+
encoder_model_name="roberta-base",
|
| 29 |
+
frame_qa_model_name="nixie1981/sem_frames",
|
| 30 |
+
source_qa_model_name=None,
|
| 31 |
+
classifier_hidden=768,
|
| 32 |
+
drop_ratio=0.2,
|
| 33 |
+
num_labels=2,
|
| 34 |
+
source_blend_mode='replacement',
|
| 35 |
+
source_use_mode='metaphor_only',
|
| 36 |
+
source_alpha=0.3,
|
| 37 |
+
metaphor_threshold=0.5,
|
| 38 |
+
):
|
| 39 |
+
super().__init__()
|
| 40 |
+
|
| 41 |
+
self.num_labels = num_labels
|
| 42 |
+
self.classifier_hidden = classifier_hidden
|
| 43 |
+
self.drop_ratio = drop_ratio
|
| 44 |
+
|
| 45 |
+
# Configuration
|
| 46 |
+
self.source_blend_mode = source_blend_mode
|
| 47 |
+
self.source_use_mode = source_use_mode
|
| 48 |
+
self.source_alpha = source_alpha
|
| 49 |
+
self.metaphor_threshold = metaphor_threshold
|
| 50 |
+
|
| 51 |
+
# Load encoder (RoBERTa)
|
| 52 |
+
self.encoder = RobertaModel.from_pretrained(encoder_model_name)
|
| 53 |
+
self.tokenizer = RobertaTokenizer.from_pretrained(encoder_model_name)
|
| 54 |
+
self.config = self.encoder.config
|
| 55 |
+
|
| 56 |
+
# Load frame QA model
|
| 57 |
+
try:
|
| 58 |
+
self.frame_qa_model = AutoModelForQuestionAnswering.from_pretrained(frame_qa_model_name)
|
| 59 |
+
self.frame_qa_tokenizer = AutoTokenizer.from_pretrained(frame_qa_model_name)
|
| 60 |
+
self.has_frame_predictor = True
|
| 61 |
+
except:
|
| 62 |
+
print("Warning: Frame QA model not available")
|
| 63 |
+
self.has_frame_predictor = False
|
| 64 |
+
|
| 65 |
+
# Load source QA model (if available)
|
| 66 |
+
if source_qa_model_name:
|
| 67 |
+
try:
|
| 68 |
+
self.source_qa_model = AutoModelForQuestionAnswering.from_pretrained(source_qa_model_name)
|
| 69 |
+
self.source_qa_tokenizer = AutoTokenizer.from_pretrained(source_qa_model_name)
|
| 70 |
+
self.has_source_predictor = True
|
| 71 |
+
except:
|
| 72 |
+
print("Warning: Source QA model not available")
|
| 73 |
+
self.has_source_predictor = False
|
| 74 |
+
else:
|
| 75 |
+
self.has_source_predictor = False
|
| 76 |
+
|
| 77 |
+
# Dropout
|
| 78 |
+
self.dropout = nn.Dropout(drop_ratio)
|
| 79 |
+
|
| 80 |
+
# Classification layers
|
| 81 |
+
self.SPV_linear = nn.Linear(self.config.hidden_size * 2, classifier_hidden)
|
| 82 |
+
self.MIP_linear = nn.Linear(self.config.hidden_size * 2, classifier_hidden)
|
| 83 |
+
self.classifier = nn.Linear(classifier_hidden * 2, num_labels)
|
| 84 |
+
|
| 85 |
+
self._init_weights(self.SPV_linear)
|
| 86 |
+
self._init_weights(self.MIP_linear)
|
| 87 |
+
self._init_weights(self.classifier)
|
| 88 |
+
|
| 89 |
+
self.logsoftmax = nn.LogSoftmax(dim=1)
|
| 90 |
+
|
| 91 |
+
# Load source and frame labels
|
| 92 |
+
self.source_id2label = {}
|
| 93 |
+
self.frame_id2label = {}
|
| 94 |
+
|
| 95 |
+
def _init_weights(self, module):
|
| 96 |
+
"""Initialize the weights"""
|
| 97 |
+
if isinstance(module, (nn.Linear, nn.Embedding)):
|
| 98 |
+
module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
|
| 99 |
+
if isinstance(module, nn.Linear) and module.bias is not None:
|
| 100 |
+
module.bias.data.zero_()
|
| 101 |
+
|
| 102 |
+
def predict_frames(self, sentence: str, target_word: str) -> Dict[str, any]:
|
| 103 |
+
"""
|
| 104 |
+
Predict semantic frame for a target word in context
|
| 105 |
+
|
| 106 |
+
Args:
|
| 107 |
+
sentence: Input sentence
|
| 108 |
+
target_word: Target word to analyze
|
| 109 |
+
|
| 110 |
+
Returns:
|
| 111 |
+
Dictionary with frame prediction and confidence
|
| 112 |
+
"""
|
| 113 |
+
if not self.has_frame_predictor:
|
| 114 |
+
return {"frame": "UNKNOWN", "confidence": 0.0}
|
| 115 |
+
|
| 116 |
+
inputs = self.frame_qa_tokenizer(
|
| 117 |
+
sentence,
|
| 118 |
+
target_word,
|
| 119 |
+
max_length=150,
|
| 120 |
+
padding='max_length',
|
| 121 |
+
truncation=True,
|
| 122 |
+
return_tensors='pt'
|
| 123 |
+
)
|
| 124 |
+
|
| 125 |
+
with torch.no_grad():
|
| 126 |
+
outputs = self.frame_qa_model(**inputs)
|
| 127 |
+
start_logits = outputs.start_logits
|
| 128 |
+
end_logits = outputs.end_logits
|
| 129 |
+
|
| 130 |
+
start_idx = torch.argmax(start_logits)
|
| 131 |
+
end_idx = torch.argmax(end_logits)
|
| 132 |
+
|
| 133 |
+
confidence = (torch.max(torch.softmax(start_logits, dim=-1)) +
|
| 134 |
+
torch.max(torch.softmax(end_logits, dim=-1))) / 2.0
|
| 135 |
+
|
| 136 |
+
frame_tokens = inputs['input_ids'][0][start_idx:end_idx+1]
|
| 137 |
+
frame = self.frame_qa_tokenizer.decode(frame_tokens, skip_special_tokens=True)
|
| 138 |
+
|
| 139 |
+
return {
|
| 140 |
+
"frame": frame if frame else "UNKNOWN",
|
| 141 |
+
"confidence": confidence.item()
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
def predict_source(self, sentence: str, target_word: str) -> Dict[str, any]:
|
| 145 |
+
"""
|
| 146 |
+
Predict source domain for a metaphor
|
| 147 |
+
|
| 148 |
+
Args:
|
| 149 |
+
sentence: Input sentence
|
| 150 |
+
target_word: Target word to analyze
|
| 151 |
+
|
| 152 |
+
Returns:
|
| 153 |
+
Dictionary with source prediction and confidence
|
| 154 |
+
"""
|
| 155 |
+
if not self.has_source_predictor:
|
| 156 |
+
return {"source": "UNKNOWN", "confidence": 0.0}
|
| 157 |
+
|
| 158 |
+
inputs = self.source_qa_tokenizer(
|
| 159 |
+
sentence,
|
| 160 |
+
target_word,
|
| 161 |
+
max_length=150,
|
| 162 |
+
padding='max_length',
|
| 163 |
+
truncation=True,
|
| 164 |
+
return_tensors='pt'
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
with torch.no_grad():
|
| 168 |
+
outputs = self.source_qa_model(**inputs)
|
| 169 |
+
logits = outputs.logits if hasattr(outputs, 'logits') else outputs.start_logits
|
| 170 |
+
|
| 171 |
+
probs = torch.softmax(logits, dim=-1)
|
| 172 |
+
predicted_id = torch.argmax(probs, dim=-1)
|
| 173 |
+
confidence = probs.gather(-1, predicted_id.unsqueeze(-1)).squeeze(-1)
|
| 174 |
+
|
| 175 |
+
source = self.source_id2label.get(predicted_id.item(), "UNKNOWN")
|
| 176 |
+
|
| 177 |
+
return {
|
| 178 |
+
"source": source,
|
| 179 |
+
"confidence": confidence.item()
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
def predict_metaphor(
|
| 183 |
+
self,
|
| 184 |
+
sentence: str,
|
| 185 |
+
target_word: str,
|
| 186 |
+
target_positions: Optional[List[int]] = None
|
| 187 |
+
) -> Dict[str, any]:
|
| 188 |
+
"""
|
| 189 |
+
Predict if target word is metaphorical in context
|
| 190 |
+
|
| 191 |
+
Args:
|
| 192 |
+
sentence: Input sentence
|
| 193 |
+
target_word: Target word to analyze
|
| 194 |
+
target_positions: Token positions of target word (optional)
|
| 195 |
+
|
| 196 |
+
Returns:
|
| 197 |
+
Dictionary with metaphor prediction, frame, and source
|
| 198 |
+
"""
|
| 199 |
+
# Tokenize input
|
| 200 |
+
inputs = self.tokenizer(
|
| 201 |
+
sentence,
|
| 202 |
+
max_length=150,
|
| 203 |
+
padding='max_length',
|
| 204 |
+
truncation=True,
|
| 205 |
+
return_tensors='pt'
|
| 206 |
+
)
|
| 207 |
+
|
| 208 |
+
# Create target mask
|
| 209 |
+
if target_positions is None:
|
| 210 |
+
# Find target word positions
|
| 211 |
+
target_tokens = self.tokenizer.tokenize(target_word)
|
| 212 |
+
sentence_tokens = self.tokenizer.tokenize(sentence)
|
| 213 |
+
target_positions = []
|
| 214 |
+
for i in range(len(sentence_tokens) - len(target_tokens) + 1):
|
| 215 |
+
if sentence_tokens[i:i+len(target_tokens)] == target_tokens:
|
| 216 |
+
target_positions = list(range(i+1, i+1+len(target_tokens))) # +1 for CLS token
|
| 217 |
+
break
|
| 218 |
+
|
| 219 |
+
target_mask = torch.zeros_like(inputs['input_ids'], dtype=torch.float)
|
| 220 |
+
if target_positions:
|
| 221 |
+
for pos in target_positions:
|
| 222 |
+
if pos < target_mask.size(1):
|
| 223 |
+
target_mask[0, pos] = 1.0
|
| 224 |
+
|
| 225 |
+
# Forward pass for metaphor detection
|
| 226 |
+
with torch.no_grad():
|
| 227 |
+
outputs = self.encoder(**inputs)
|
| 228 |
+
sequence_output = outputs[0]
|
| 229 |
+
pooled_output = outputs[1]
|
| 230 |
+
|
| 231 |
+
# Get target output
|
| 232 |
+
target_output = sequence_output * target_mask.unsqueeze(2)
|
| 233 |
+
target_output = target_output.sum(dim=1) / (target_mask.sum(-1, keepdim=True) + 1e-10)
|
| 234 |
+
target_output = self.dropout(target_output)
|
| 235 |
+
pooled_output = self.dropout(pooled_output)
|
| 236 |
+
|
| 237 |
+
# SPV and MIP
|
| 238 |
+
SPV_hidden = self.SPV_linear(torch.cat([pooled_output, target_output], dim=1))
|
| 239 |
+
MIP_hidden = self.MIP_linear(torch.cat([target_output, target_output], dim=1))
|
| 240 |
+
|
| 241 |
+
# Classification
|
| 242 |
+
logits = self.classifier(torch.cat([SPV_hidden, MIP_hidden], dim=1))
|
| 243 |
+
logits = self.logsoftmax(logits)
|
| 244 |
+
probs = torch.exp(logits)
|
| 245 |
+
|
| 246 |
+
is_metaphor = torch.argmax(probs, dim=1).item() == 1
|
| 247 |
+
metaphor_confidence = probs[0, 1].item()
|
| 248 |
+
|
| 249 |
+
# Predict frame and source
|
| 250 |
+
frame_result = self.predict_frames(sentence, target_word)
|
| 251 |
+
source_result = self.predict_source(sentence, target_word) if is_metaphor else {"source": "N/A", "confidence": 0.0}
|
| 252 |
+
|
| 253 |
+
return {
|
| 254 |
+
"is_metaphor": is_metaphor,
|
| 255 |
+
"metaphor_confidence": metaphor_confidence,
|
| 256 |
+
"frame": frame_result["frame"],
|
| 257 |
+
"frame_confidence": frame_result["confidence"],
|
| 258 |
+
"source": source_result["source"],
|
| 259 |
+
"source_confidence": source_result["confidence"]
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
@classmethod
|
| 263 |
+
def from_pretrained(cls, model_path, **kwargs):
|
| 264 |
+
"""Load model from pretrained checkpoint"""
|
| 265 |
+
# Load config
|
| 266 |
+
config_path = os.path.join(model_path, "config.json")
|
| 267 |
+
with open(config_path, 'r') as f:
|
| 268 |
+
config = json.load(f)
|
| 269 |
+
|
| 270 |
+
# Initialize model
|
| 271 |
+
model = cls(**kwargs)
|
| 272 |
+
|
| 273 |
+
# Load weights
|
| 274 |
+
weights_path = os.path.join(model_path, "pytorch_model.bin")
|
| 275 |
+
if os.path.exists(weights_path):
|
| 276 |
+
state_dict = torch.load(weights_path, map_location='cpu')
|
| 277 |
+
model.load_state_dict(state_dict, strict=False)
|
| 278 |
+
|
| 279 |
+
return model
|
| 280 |
+
|
| 281 |
+
def save_pretrained(self, save_directory):
|
| 282 |
+
"""Save model to directory"""
|
| 283 |
+
os.makedirs(save_directory, exist_ok=True)
|
| 284 |
+
|
| 285 |
+
# Save weights
|
| 286 |
+
torch.save(self.state_dict(), os.path.join(save_directory, "pytorch_model.bin"))
|
| 287 |
+
|
| 288 |
+
# Save config
|
| 289 |
+
config = {
|
| 290 |
+
"_name_or_path": "ConceptFrameMet",
|
| 291 |
+
"architectures": ["ConceptFrameMetForMetaphorDetection"],
|
| 292 |
+
"model_type": "conceptframemet",
|
| 293 |
+
"num_labels": self.num_labels,
|
| 294 |
+
"classifier_hidden": self.classifier_hidden,
|
| 295 |
+
"drop_ratio": self.drop_ratio,
|
| 296 |
+
"source_blend_mode": self.source_blend_mode,
|
| 297 |
+
"source_use_mode": self.source_use_mode,
|
| 298 |
+
"source_alpha": self.source_alpha,
|
| 299 |
+
"metaphor_threshold": self.metaphor_threshold,
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
with open(os.path.join(save_directory, "config.json"), 'w') as f:
|
| 303 |
+
json.dump(config, f, indent=2)
|
| 304 |
+
|
| 305 |
+
# Save tokenizer
|
| 306 |
+
self.tokenizer.save_pretrained(save_directory)
|
pytorch_model.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1748be3cb0f48bd43178259ec76ec963e8db33c21c1e6eebf1991448ce468443
|
| 3 |
+
size 1508249917
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch>=1.6.0
|
| 2 |
+
transformers>=4.30.2
|
| 3 |
+
numpy>=1.20.0
|
| 4 |
+
scipy>=1.6.0
|
| 5 |
+
scikit-learn>=0.24.1
|
| 6 |
+
tqdm>=4.56.0
|
| 7 |
+
datasets>=2.14.0
|
| 8 |
+
nltk>=3.5
|
test_model.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Test script for ConceptFrameMet model
|
| 3 |
+
|
| 4 |
+
This script tests basic model loading and inference capabilities.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
from transformers import RobertaTokenizer
|
| 9 |
+
import json
|
| 10 |
+
import sys
|
| 11 |
+
import os
|
| 12 |
+
|
| 13 |
+
print("="*60)
|
| 14 |
+
print("ConceptFrameMet Model Test")
|
| 15 |
+
print("="*60)
|
| 16 |
+
|
| 17 |
+
# Set model path
|
| 18 |
+
model_path = "/data/gpfs/projects/punim0478/otmakhovay/ConceptFrameMet"
|
| 19 |
+
|
| 20 |
+
print(f"\n1. Testing file presence...")
|
| 21 |
+
required_files = [
|
| 22 |
+
"pytorch_model.bin",
|
| 23 |
+
"config.json",
|
| 24 |
+
"vocab.json",
|
| 25 |
+
"merges.txt"
|
| 26 |
+
]
|
| 27 |
+
|
| 28 |
+
for file in required_files:
|
| 29 |
+
filepath = os.path.join(model_path, file)
|
| 30 |
+
if os.path.exists(filepath):
|
| 31 |
+
size = os.path.getsize(filepath)
|
| 32 |
+
size_mb = size / (1024 * 1024)
|
| 33 |
+
print(f" β {file}: {size_mb:.2f} MB")
|
| 34 |
+
else:
|
| 35 |
+
print(f" β {file}: MISSING")
|
| 36 |
+
sys.exit(1)
|
| 37 |
+
|
| 38 |
+
print(f"\n2. Loading tokenizer...")
|
| 39 |
+
try:
|
| 40 |
+
tokenizer = RobertaTokenizer.from_pretrained(model_path)
|
| 41 |
+
print(f" β Tokenizer loaded successfully")
|
| 42 |
+
print(f" - Vocab size: {tokenizer.vocab_size}")
|
| 43 |
+
except Exception as e:
|
| 44 |
+
print(f" β Error loading tokenizer: {e}")
|
| 45 |
+
sys.exit(1)
|
| 46 |
+
|
| 47 |
+
print(f"\n3. Loading config...")
|
| 48 |
+
try:
|
| 49 |
+
with open(f"{model_path}/config.json", 'r') as f:
|
| 50 |
+
config = json.load(f)
|
| 51 |
+
print(f" β Config loaded successfully")
|
| 52 |
+
print(f" - Model type: {config.get('model_type', 'roberta')}")
|
| 53 |
+
print(f" - Hidden size: {config.get('hidden_size', 768)}")
|
| 54 |
+
print(f" - Layers: {config.get('num_hidden_layers', 12)}")
|
| 55 |
+
except Exception as e:
|
| 56 |
+
print(f" β Error loading config: {e}")
|
| 57 |
+
sys.exit(1)
|
| 58 |
+
|
| 59 |
+
print(f"\n4. Loading model weights...")
|
| 60 |
+
try:
|
| 61 |
+
state_dict = torch.load(f"{model_path}/pytorch_model.bin", map_location='cpu')
|
| 62 |
+
print(f" β Model weights loaded successfully")
|
| 63 |
+
print(f" - Number of parameters: {len(state_dict)}")
|
| 64 |
+
|
| 65 |
+
# Show some key layers
|
| 66 |
+
print(f" - Sample layers:")
|
| 67 |
+
for i, key in enumerate(list(state_dict.keys())[:5]):
|
| 68 |
+
shape = state_dict[key].shape if hasattr(state_dict[key], 'shape') else 'scalar'
|
| 69 |
+
print(f" β’ {key}: {shape}")
|
| 70 |
+
except Exception as e:
|
| 71 |
+
print(f" β Error loading weights: {e}")
|
| 72 |
+
sys.exit(1)
|
| 73 |
+
|
| 74 |
+
print(f"\n5. Testing tokenization...")
|
| 75 |
+
try:
|
| 76 |
+
test_sentence = "The company is navigating through troubled waters"
|
| 77 |
+
test_target = "navigating"
|
| 78 |
+
|
| 79 |
+
# Tokenize sentence
|
| 80 |
+
inputs = tokenizer(
|
| 81 |
+
test_sentence,
|
| 82 |
+
max_length=150,
|
| 83 |
+
padding='max_length',
|
| 84 |
+
truncation=True,
|
| 85 |
+
return_tensors='pt'
|
| 86 |
+
)
|
| 87 |
+
|
| 88 |
+
print(f" β Tokenization successful")
|
| 89 |
+
print(f" - Sentence: '{test_sentence}'")
|
| 90 |
+
print(f" - Target: '{test_target}'")
|
| 91 |
+
print(f" - Input shape: {inputs['input_ids'].shape}")
|
| 92 |
+
|
| 93 |
+
# Find target positions
|
| 94 |
+
target_tokens = tokenizer.tokenize(test_target)
|
| 95 |
+
sentence_tokens = tokenizer.tokenize(test_sentence)
|
| 96 |
+
|
| 97 |
+
target_positions = []
|
| 98 |
+
for i in range(len(sentence_tokens) - len(target_tokens) + 1):
|
| 99 |
+
if sentence_tokens[i:i+len(target_tokens)] == target_tokens:
|
| 100 |
+
target_positions = list(range(i+1, i+1+len(target_tokens)))
|
| 101 |
+
break
|
| 102 |
+
|
| 103 |
+
print(f" - Target found at positions: {target_positions}")
|
| 104 |
+
|
| 105 |
+
except Exception as e:
|
| 106 |
+
print(f" β Error during tokenization: {e}")
|
| 107 |
+
sys.exit(1)
|
| 108 |
+
|
| 109 |
+
print(f"\n6. Checking model compatibility...")
|
| 110 |
+
try:
|
| 111 |
+
from modeling_conceptframemet import ConceptFrameMetForMetaphorDetection
|
| 112 |
+
print(f" β Custom model class can be imported")
|
| 113 |
+
except Exception as e:
|
| 114 |
+
print(f" β Warning: Could not import custom model class: {e}")
|
| 115 |
+
print(f" This is OK - the model can still be used with standard transformers")
|
| 116 |
+
|
| 117 |
+
print(f"\n" + "="*60)
|
| 118 |
+
print("β ALL TESTS PASSED!")
|
| 119 |
+
print("="*60)
|
| 120 |
+
print(f"\nYour ConceptFrameMet model is ready for upload to Hugging Face!")
|
| 121 |
+
print(f"\nModel summary:")
|
| 122 |
+
print(f" - Location: {model_path}")
|
| 123 |
+
print(f" - Total size: ~1.5 GB")
|
| 124 |
+
print(f" - Base model: RoBERTa-base")
|
| 125 |
+
print(f" - Epoch: 3 (best checkpoint)")
|
| 126 |
+
print(f" - Capabilities:")
|
| 127 |
+
print(f" β’ Metaphor detection")
|
| 128 |
+
print(f" β’ Frame prediction (with nixie1981/sem_frames)")
|
| 129 |
+
print(f" β’ Source domain prediction")
|
| 130 |
+
print(f"\nNext step: Follow HUGGINGFACE_UPLOAD_GUIDE.md to upload!")
|
| 131 |
+
print("="*60)
|
vocab.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|