mirror of
https://github.com/task-17-lct/backend.git
synced 2024-11-24 00:13:43 +03:00
Merge branch 'path-generate'
This commit is contained in:
commit
67260adb55
46
passfinder/recomendations/migrations/0003_nearestevent.py
Normal file
46
passfinder/recomendations/migrations/0003_nearestevent.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
# Generated by Django 4.2.1 on 2023-05-22 17:09
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("events", "0016_remove_basepoint_location_remove_city_location_and_more"),
|
||||||
|
(
|
||||||
|
"recomendations",
|
||||||
|
"0002_rename_unpreffered_lays_userpreferences_unpreffered_plays",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="NearestEvent",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"event",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="nearest_model_rel",
|
||||||
|
to="events.event",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"nearest",
|
||||||
|
models.ManyToManyField(
|
||||||
|
related_name="nearest_model_rev_rel", to="events.event"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -13,4 +13,9 @@ class UserPreferences(models.Model):
|
||||||
unpreffered_movies = models.ManyToManyField(Event, related_name='unpreffered_user_movie')
|
unpreffered_movies = models.ManyToManyField(Event, related_name='unpreffered_user_movie')
|
||||||
|
|
||||||
preferred_concerts = models.ManyToManyField(Event, related_name='preffered_users_concert')
|
preferred_concerts = models.ManyToManyField(Event, related_name='preffered_users_concert')
|
||||||
unpreferred_concerts = models.ManyToManyField(Event, related_name='unpreffered_users_concert')
|
unpreferred_concerts = models.ManyToManyField(Event, related_name='unpreffered_users_concert')
|
||||||
|
|
||||||
|
|
||||||
|
class NearestEvent(models.Model):
|
||||||
|
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='nearest_model_rel')
|
||||||
|
nearest = models.ManyToManyField(Event, related_name='nearest_model_rev_rel')
|
|
@ -6,21 +6,29 @@
|
||||||
excursion_mapping = None
|
excursion_mapping = None
|
||||||
concert_mapping = None
|
concert_mapping = None
|
||||||
|
|
||||||
|
|
||||||
|
def build_dict(list_mapping):
|
||||||
|
mapping = {}
|
||||||
|
for idx, elem in enumerate(list_mapping):
|
||||||
|
mapping.update({elem: idx})
|
||||||
|
return mapping
|
||||||
|
|
||||||
|
|
||||||
with open('passfinder/recomendations/service/mapping/attractions.pickle', 'rb') as file:
|
with open('passfinder/recomendations/service/mapping/attractions.pickle', 'rb') as file:
|
||||||
attraction_mapping = pickle.load(file)
|
attraction_mapping = build_dict(pickle.load(file))
|
||||||
|
|
||||||
|
|
||||||
with open('passfinder/recomendations/service/mapping/kino.pickle', 'rb') as file:
|
with open('passfinder/recomendations/service/mapping/kino.pickle', 'rb') as file:
|
||||||
cinema_mapping = pickle.load(file)
|
cinema_mapping = build_dict(pickle.load(file))
|
||||||
|
|
||||||
|
|
||||||
with open('passfinder/recomendations/service/mapping/spektakli.pickle', 'rb') as file:
|
with open('passfinder/recomendations/service/mapping/spektakli.pickle', 'rb') as file:
|
||||||
plays_mapping = pickle.load(file)
|
plays_mapping = build_dict(pickle.load(file))
|
||||||
|
|
||||||
|
|
||||||
with open('passfinder/recomendations/service/mapping/excursii.pickle', 'rb') as file:
|
with open('passfinder/recomendations/service/mapping/excursii.pickle', 'rb') as file:
|
||||||
excursion_mapping = pickle.load(file)
|
excursion_mapping = build_dict(pickle.load(file))
|
||||||
|
|
||||||
|
|
||||||
with open('passfinder/recomendations/service/mapping/concerts.pickle', 'rb') as file:
|
with open('passfinder/recomendations/service/mapping/concerts.pickle', 'rb') as file:
|
||||||
concert_mapping = pickle.load(file)
|
concert_mapping = build_dict(pickle.load(file))
|
|
@ -1,16 +1,18 @@
|
||||||
from annoy import AnnoyIndex
|
from annoy import AnnoyIndex
|
||||||
from .mapping.mapping import *
|
from .mapping.mapping import *
|
||||||
from .models.models import *
|
from .models.models import *
|
||||||
from passfinder.events.models import Event
|
from passfinder.events.models import Event, Region
|
||||||
from passfinder.recomendations.models import UserPreferences
|
from passfinder.recomendations.models import UserPreferences, NearestEvent
|
||||||
from random import choice
|
from random import choice
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
from passfinder.users.models import User
|
||||||
|
from collections.abc import Iterable
|
||||||
|
|
||||||
|
|
||||||
def get_nearest_(instance_model, model_type, mapping, nearest_n, ml_model):
|
def get_nearest_(instance_model, model_type, mapping, nearest_n, ml_model):
|
||||||
how_many = len(Event.objects.filter(type=model_type))
|
how_many = len(Event.objects.filter(type=model_type))
|
||||||
|
|
||||||
index = mapping.index(instance_model.oid)
|
index = mapping[instance_model.oid]
|
||||||
nearest = ml_model.get_nns_by_item(index, len(mapping))
|
nearest = ml_model.get_nns_by_item(index, len(mapping))
|
||||||
|
|
||||||
res = []
|
res = []
|
||||||
|
@ -182,3 +184,89 @@ def get_personal_movies_recommendation(user):
|
||||||
prefer = pref.preffered_movies.all()
|
prefer = pref.preffered_movies.all()
|
||||||
unprefer = pref.unpreffered_movies.all()
|
unprefer = pref.unpreffered_movies.all()
|
||||||
return get_personal_recommendation(prefer, unprefer)
|
return get_personal_recommendation(prefer, unprefer)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def dist_func(event1: Event, event2: Event):
|
||||||
|
return (event1.lat - event2.lat) ** 2 + (event2.lon - event2.lon) ** 2
|
||||||
|
|
||||||
|
|
||||||
|
def generate_nearest():
|
||||||
|
NearestEvent.objects.all().delete()
|
||||||
|
all_events = list(Event.objects.all())
|
||||||
|
for i, event in enumerate(Event.objects.all()):
|
||||||
|
event_all_events = list(sorted(all_events.copy(), key=lambda x: dist_func(event, x)))
|
||||||
|
nearest = NearestEvent.objects.create(event=event)
|
||||||
|
nearest.nearest.set(event_all_events[0:100])
|
||||||
|
nearest.save()
|
||||||
|
if i % 100 == 0:
|
||||||
|
print(i)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_mean_metric(favorite_events: Iterable[Event], target_event: Event, model: AnnoyIndex, rev_list: Iterable[str]):
|
||||||
|
if not len(favorite_events):
|
||||||
|
return 100000
|
||||||
|
|
||||||
|
dists = []
|
||||||
|
target_event_idx = rev_list[target_event.oid]
|
||||||
|
for fav in favorite_events:
|
||||||
|
dists.append(model.get_distance(rev_list[fav.oid], target_event_idx))
|
||||||
|
return sum(dists) / len(dists)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_favorite_metric(event: Event, user: User):
|
||||||
|
pref = UserPreferences.objects.get(user=user)
|
||||||
|
if event.type == 'plays':
|
||||||
|
preferred = pref.preffered_plays.all()
|
||||||
|
return calculate_mean_metric(
|
||||||
|
preferred,
|
||||||
|
event,
|
||||||
|
plays_model,
|
||||||
|
plays_mapping
|
||||||
|
)
|
||||||
|
if event.type == 'concert':
|
||||||
|
preferred = pref.preferred_concerts.all()
|
||||||
|
return calculate_mean_metric(
|
||||||
|
preferred,
|
||||||
|
event,
|
||||||
|
concert_model,
|
||||||
|
concert_mapping
|
||||||
|
)
|
||||||
|
if event.type == 'movie':
|
||||||
|
preferred = pref.preffered_movies.all()
|
||||||
|
return calculate_mean_metric(
|
||||||
|
preferred,
|
||||||
|
event,
|
||||||
|
cinema_model,
|
||||||
|
cinema_mapping
|
||||||
|
)
|
||||||
|
return 1000000
|
||||||
|
|
||||||
|
|
||||||
|
def get_nearest_favorite(events: Iterable[Event], user: User, exclude_events: Iterable[Event]=[]):
|
||||||
|
result = events[0]
|
||||||
|
result_min = calculate_favorite_metric(events[0], user)
|
||||||
|
for event in events:
|
||||||
|
if event in exclude_events: continue
|
||||||
|
local_min_metric = calculate_favorite_metric(event, user)
|
||||||
|
if local_min_metric < result_min:
|
||||||
|
result_min = local_min_metric
|
||||||
|
result = event
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def generate_path(region: Region, user: User):
|
||||||
|
region_events = Event.objects.filter(region=region)
|
||||||
|
|
||||||
|
start_point = get_nearest_favorite(region_events, user, [])
|
||||||
|
|
||||||
|
candidates = NearestEvent.objects.get(event=start_point).nearest.all()
|
||||||
|
|
||||||
|
points = [start_point]
|
||||||
|
|
||||||
|
while len(points) < 5:
|
||||||
|
candidates = NearestEvent.objects.get(event=points[-1]).nearest.all()
|
||||||
|
points.append(get_nearest_favorite(candidates, user, points))
|
||||||
|
|
||||||
|
return points
|
||||||
|
|
Loading…
Reference in New Issue
Block a user