File size: 9,186 Bytes
937277a
 
 
 
 
1f97ba7
937277a
 
 
 
1f97ba7
26ce09f
937277a
 
 
 
 
 
 
 
 
 
0df8b32
987cd51
 
937277a
 
 
 
 
1f97ba7
937277a
1f97ba7
937277a
 
1f97ba7
c760c4d
937277a
1f97ba7
 
 
937277a
7e40316
 
 
937277a
1f97ba7
 
 
 
 
7e40316
 
1f97ba7
 
7e40316
 
 
 
 
 
 
 
1f97ba7
 
 
 
7e40316
1f97ba7
7e40316
 
 
 
 
 
 
 
 
1f97ba7
 
 
 
 
 
 
 
937277a
86c2ace
1f97ba7
 
 
 
 
 
 
 
 
 
 
 
 
 
937277a
 
 
fabd526
1f97ba7
937277a
 
 
2146f8c
 
1f97ba7
 
 
937277a
 
 
fabd526
 
937277a
 
 
 
 
fabd526
 
 
 
 
 
 
 
 
2146f8c
 
c760c4d
937277a
1f97ba7
937277a
 
1f97ba7
937277a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44e7110
 
 
2146f8c
44e7110
 
 
 
 
 
 
 
fabd526
 
 
2146f8c
c760c4d
44e7110
 
 
 
 
 
937277a
 
 
44e7110
 
 
 
 
 
 
937277a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c760c4d
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
---
language: en
license: apache-2.0
tags:
- sentence-transformers
- transformers
- opinion-mining
- stance-detection
- social-computing
- LoRA
base_model: sentence-transformers/all-mpnet-base-v2
# library_name: peft
---

# Stance-Aware Sentence Transformers for Opinion Mining

## Model Overview

This model is fine-tuned on top of `sentence-transformers/all-mpnet-base-v2` to differentiate between opposing viewpoints on the same topic. Traditional sentence transformers group topically similar texts together but struggle to recognize nuanced differences in stance—such as differentiating the opinions "I love pineapple on pizza" and "I hate pineapple on pizza." This stance-aware sentence transformer addresses this limitation by fine-tuning with arguments both for and against controversial topics, making it especially useful for applications in social computing, such as **opinion mining** and **stance detection**.

### Research Background

As explained in our [EMNLP 2024 paper](https://scholar.google.com/citations?view_op=view_citation&hl=en&user=RnPFjYcAAAAJ&citation_for_view=RnPFjYcAAAAJ:W7OEmFMy1HYC), this model was fine-tuned using contrastive learning on human-generated arguments for and against various claims. This technique enhances sentence transformers' ability to capture sentiment and stance in opinionated texts while retaining computational efficiency over classification-based approaches.
The code for training can be viewed from [this repository](https://github.com/vahidthegreat/StanceAware_SBERT/) at huggingface.


## Model Use and Code Instructions

### Loading and Using the Model with LoRA Weights

Since this model leverages LoRA (Low-Rank Adaptation) fine-tuning, you only need to download the lightweight LoRA weights and apply them to the base model. Below are two guides on loading and applying the LoRA weights to `sentence-transformers/all-mpnet-base-v2` based on Sentence Transformers and Transformers, respectively.

#### with Sentence Transformers

```bash
pip install peft sentence-transformers
```

```python
from sentence_transformers import SentenceTransformer
from peft import PeftModel

base_model = SentenceTransformer("all-mpnet-base-v2")
finetuned_model = SentenceTransformer("all-mpnet-base-v2")
finetuned_model[0].auto_model = PeftModel.from_pretrained(finetuned_model[0].auto_model, "vahidthegreat/StanceAware-SBERT")

sentences = [
    "I love pineapple on pizza",
    "I hate pineapple on pizza",
    "I like pineapple on pizza",
]
embeddings = base_model.encode(sentences)
print('Embedding Shape:')
print(embeddings.shape)

similarity = base_model.similarity(embeddings, embeddings)
print('\n\nSimilarity Matrix for the Base Model:')
print(similarity)


embeddings = finetuned_model.encode(sentences)
similarity = finetuned_model.similarity(embeddings, embeddings)
print('\n\nSimilarity Matrix for the FineTuned Model:')
print(similarity)
```

```output
Embedding Shape:
(3, 768)


Similarity Matrix for the Base Model:
tensor([[1.0000, 0.8591, 0.9774],
        [0.8591, 1.0000, 0.8561],
        [0.9774, 0.8561, 1.0000]])


Similarity Matrix for the FineTuned Model:
tensor([[1.0000, 0.5732, 0.9713],
        [0.5732, 1.0000, 0.5804],
        [0.9713, 0.5804, 1.0000]])
```
From these results we can see that the first and third sentence are very similar, while the second sentence is less similar to the other two.

#### with Transformers
First, ensure you have the required libraries installed:

```bash
pip install peft transformers torch
```

#### Using the Model with the Siamese Network Class

The following custom `SiameseNetworkMPNet` class leverages the model for stance detection tasks. It pools embeddings and normalizes them for similarity calculations. This is for the sake of replicability of our exact results. But the model would work without this as well.

```python
from peft import PeftModel
from transformers import AutoModel, AutoTokenizer
import torch
import torch.nn as nn
import torch.nn.functional as F

class SiameseNetworkMPNet(nn.Module):
    def __init__(self, model_name, tokenizer, normalize=True):
        super(SiameseNetworkMPNet, self).__init__()

        self.model = AutoModel.from_pretrained(model_name)
        self.normalize = normalize
        self.tokenizer = tokenizer

    def apply_lora_weights(self, finetuned_model):
        self.model = PeftModel.from_pretrained(self.model, finetuned_model)
        self.model = self.model.merge_and_unload()
        return self

    def forward(self, **inputs):
        model_output = self.model(**inputs)
        attention_mask = inputs['attention_mask']
        last_hidden_states = model_output.last_hidden_state  # First element of model_output contains all token embeddings
        embeddings = torch.sum(last_hidden_states * attention_mask.unsqueeze(-1), 1) / torch.clamp(attention_mask.sum(1, keepdim=True), min=1e-9) # mean_pooling
        if self.normalize:
            embeddings = F.layer_norm(embeddings, embeddings.shape[1:])
            embeddings = F.normalize(embeddings, p=2, dim=1)

        return embeddings


base_model_name = "sentence-transformers/all-mpnet-base-v2" 
tokenizer = AutoTokenizer.from_pretrained(base_model_name)

# Load the base model
base_model = SiameseNetworkMPNet(model_name=base_model_name, tokenizer=tokenizer)

# Load and apply LoRA weights
finetuned_model = SiameseNetworkMPNet(model_name=base_model_name, tokenizer=tokenizer)
finetuned_model.apply_lora_weights("vahidthegreat/StanceAware-SBERT")
```

#### Example Usage for Two-Sentence Similarity
The following example shows how to use the Siamese network with two input sentences, calculating cosine similarity to compare stances.

```python
from sklearn.metrics.pairwise import cosine_similarity

def two_sentence_similarity(model, tokenizer, text1, text2):
    # Tokenize both texts
    tokens1 = tokenizer(text1, return_tensors="pt", max_length=128, truncation=True, padding="max_length")
    tokens2 = tokenizer(text2, return_tensors="pt", max_length=128, truncation=True, padding="max_length")
    
    # Generate embeddings
    embeddings1 = model(**tokens1).detach().cpu().numpy()
    embeddings2 = model(**tokens2).detach().cpu().numpy()
    
    # Compute cosine similarity
    similarity = cosine_similarity(embeddings1, embeddings2)
    print(f"Cosine Similarity: {similarity[0][0]}")
    return similarity[0][0]

# Example sentences
text1 = "I love pineapple on pizza"
text2 = "I hate pineapple on pizza"

print(f"For Base Model sentences: '{text1}' and '{text2}'")
two_sentence_similarity(base_model, tokenizer, text1, text2)
print(f"\nFor FineTuned Model sentences: '{text1}' and '{text2}'")
two_sentence_similarity(finetuned_model, tokenizer, text1, text2)

print('\n\n')


# Example sentences
text1 = "I love pineapple on pizza"
text2 = "I like pineapple on pizza"

print(f"For Base Model sentences: '{text1}' and '{text2}'")
two_sentence_similarity(base_model, tokenizer, text1, text2)
print(f"\n\nFor FineTuned Model sentences: '{text1}' and '{text2}'")
two_sentence_similarity(finetuned_model, tokenizer, text1, text2)
```
```output
For Base Model sentences: 'I love pineapple on pizza' and 'I hate pineapple on pizza'
Cosine Similarity: 0.8590984344482422

For FineTuned Model sentences: 'I love pineapple on pizza' and 'I hate pineapple on pizza'
Cosine Similarity: 0.5732507705688477



For Base Model sentences: 'I love pineapple on pizza' and 'I like pineapple on pizza'
Cosine Similarity: 0.9773550033569336

For FineTuned Model sentences: 'I love pineapple on pizza' and 'I like pineapple on pizza'
Cosine Similarity: 0.9712905883789062
```

## Key Applications

This stance-aware sentence transformer model can be applied to various fields within social computing and opinion analysis. Here are some key applications:

- **Opinion Mining**: Extracting stances or sentiments on topics from a large corpus of texts.
- **Stance Detection**: Identifying whether statements are in favor of or against a specific claim.
- **Social and Political Discourse Analysis**: Useful for studying polarizing issues in social science research, particularly for nuanced or controversial topics.

## Limitations

While this model enhances stance detection capabilities, it may still encounter challenges with:
- **Nuanced or Ambiguous Statements**: For extremely context-dependent or subtle differences in stance, additional fine-tuning may be required.
- **Complex Multi-Sentence Arguments**: In cases where multiple arguments or perspectives are embedded within a single text, further customization or model adjustments may improve accuracy.

## Citation

If you use this model in your research, please cite our paper:

```bibtex
@inproceedings{ghafouri2024stance,
  title={I love pineapple on pizza != I hate pineapple on pizza: Stance-Aware Sentence Transformers for Opinion Mining},
  author={Ghafouri, Vahid and Such, Jose and Suarez-Tangil, Guillermo},
  booktitle={Proceedings of the 2024 Conference on Empirical Methods in Natural Language Processing (EMNLP)},
  year={2024},
  month={November 14},
  url={https://hdl.handle.net/20.500.12761/1851},
  note={Available online at https://hdl.handle.net/20.500.12761/1851}
}
```