-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi.py
More file actions
104 lines (77 loc) · 3.46 KB
/
Copy pathapi.py
File metadata and controls
104 lines (77 loc) · 3.46 KB
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
import pandas as pd
import numpy as np
import json
import gensim.downloader as model_api
from flask import Flask, request, jsonify
from sklearn.metrics.pairwise import cosine_similarity
app = Flask(__name__)
with open('./config.json') as f:
config = json.load(f)
match_threshold = config['match_threshold']
nlp_model_name = config['nlp_model_name']
# extract segment data from source_segments.csv
source_segments = pd.read_csv("./source_segments.csv")["descriptions"].tolist()
# automatically download & load pretrained NLP model for word embedding
word_embed_model = model_api.load(nlp_model_name)
print("Loaded word embedding model from {}".format(model_api.load(nlp_model_name, return_path=True)))
def vectorize(segment: str):
"""
Vectorization of a given segment
:param segment: a given segment
:return: mean_vector: mean word vector of the given segment
"""
# split the segment into words
words = segment.split()
# vectorize the words using nlp model
vectors = []
for word in words:
if word in word_embed_model: # append word's vector if it's included in the nlp model's vocabulary
vectors.append(word_embed_model[word])
# worst case: no word vector found, return zeros, assumed as never happening
if not vectors:
vectors = np.zeros(word_embed_model.vector_size)
# obtain the mean vector of all words in the segment to represent the entire segment
mean_vector = np.mean(vectors, axis=0)
return mean_vector
def calculate_similarity(input_seg: list[str], source_seg: list[str]):
"""
Similarity calculation of vectorized input and source segments
:param input_seg: a list of segments from input json
:param source_seg: a list that refers to the source segments in source_segments.csv
:return: similarity_scores: an array of similarity scores between input and source
"""
input_vectors = np.array([vectorize(seg) for seg in input_seg]) # vectorize input segments
source_vectors = np.array([vectorize(seg) for seg in source_seg]) # vectorize source segments
similarity_scores = cosine_similarity(input_vectors, source_vectors) # calculate cosine similarity
return similarity_scores
@app.route('/match', methods=['POST'])
def match_audience_segments():
"""
Semantic matching API for audience segments.
"""
data = request.json
input_segments = data.get('input_segments')
if not input_segments:
return jsonify({'error': 'No input segments given.'}), 400
# get similarity scores between input and source segments
similarity_scores = calculate_similarity(input_segments, source_segments)
# get the best matches for each input segment
best_matches = []
for i, scores in enumerate(similarity_scores):
# get the best match's index for each input segment
best_index = scores.argmax()
# get the best match
best_match = {
"input_segment": input_segments[i],
"best_match": source_segments[best_index],
"similarity_score": float(scores[best_index])
}
# set threshold to check matches
if scores[best_index] < match_threshold:
# omit the match with low match score
best_match["similarity_score"] = "0.0"
best_match["best_match"] = "no match found"
best_matches.append(best_match)
return jsonify({'best_matches': best_matches})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)