Merge branch 'path-generate'

This commit is contained in:
ilia 2023-05-22 22:40:56 +03:00
commit 6f0e561a51
4 changed files with 156 additions and 9 deletions

View 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"
),
),
],
),
]

View File

@ -14,3 +14,8 @@ class UserPreferences(models.Model):
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')

View File

@ -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))

View 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