video_recommender.py 3.78 KB
from gensim.models import Word2Vec
import numpy as np
from numpy import dot
from numpy.linalg import norm

def recommend_videos(tags, segments, tag_model_path, video_model_path, top_k):
    # 이 함수에서 모든걸 다 함
    # tags는 label val 로 묶인 문자열 리스트임
    # tags의 길이는 segment의 길이
    # 비디오 벡터를 생성한 뒤 각 segment의 벡터와 비교해 가장 유사도 높은 segment의 인덱스 추출
    # 그 후 그 인덱스 전후 2개 총 크기 5의 커널을 생성
    # 벡터공간에서 비교한 후 추천할만한 영상의 아이디만 반환
    
    #segments는 클래스 확률 클래스 확률... 일케 저장되어 있음
    tag_vectors = Word2Vec.load(tag_model_path).wv
    video_vectors = Word2Vec().wv.load(video_model_path)
    error_tags = []
    maxSimilarSegment = 0
    maxSimilarity = -1
    
    kernel = [np.zeros(100) for i in range(0,3)]

    #우선은 비교를 뜰 입력 영상의 단일 비디오벡터를 구함
    video_vector = np.zeros(100)
    print(tags)
    for (tag, weight) in tags:
        if tag in tag_vectors.vocab:
            #float(weight)
            video_vector = video_vector + (tag_vectors[tag] * float(weight))
        else:
            # Pass if tag is unknown
            if tag not in error_tags:
                error_tags.append(tag)
                
    #각 세그먼트마다 비교를 떠서 인덱스를 저장
    currentIndex = 0
    for segment in segments:
        segment_vector = np.zeros(100)
        segTags = [segment[i] for i in range(0,len(segment),2)]
        segProbs = [float(segment[i]) for i in range(1,len(segment),2)]
        for (tag, weight) in zip(segTags,segProbs):
            if tag in tag_vectors.vocab:
                #float(weight)
                segment_vector = segment_vector + (tag_vectors[tag] * float(weight))
            else:
                # Pass if tag is unknown
                if tag not in error_tags:
                    error_tags.append(tag)
                    
        #비디오 벡터와 세그먼트 벡터 비교
        similarity = cos_sim(video_vector, segment_vector)
        if similarity > maxSimilarity:
            maxSimilarSegment = currentIndex
            maxSimilarity = similarity
            if maxSimilarSegment == 0:
               maxSimilarSegment = 1
            elif maxSimilarSegment == len(segments) - 1:
                maxSimilarSegment =  len(segments) - 2
        #세그먼트 인덱스 증가
        currentIndex = currentIndex + 1
    
    print("len=============================================")
    print(len(kernel))
    print(maxSimilarSegment)
    #커널 생성
    for k in range (0,3):
        segment = segments[maxSimilarSegment -1 + k]
        segment_vector = np.zeros(100)
        segTags = [segment[i] for i in range(0,len(segment),2)]
        print(segTags)
        segProbs = [float(segment[i]) for i in range(1,len(segment),2)]
        for (tag, weight) in zip(segTags,segProbs):
            if tag in tag_vectors.vocab:
                #float(weight)
                segment_vector = segment_vector + (tag_vectors[tag] * float(weight))
            else:
                # Pass if tag is unknown
                if tag not in error_tags:
                    error_tags.append(tag)
                   
        kernel[k] = segment_vector

    #여기에서 유사한 벡터들을 뽑아냄
    #현재는 비디오id로 영상을 얻을 수 없으므로 반환값으로 비디오 아이디와 태그들, 확률 사용
    similar_ids = [x[0] for x in video_vectors.similar_by_vector(video_vector, top_k)]
    return similar_ids
 

def cos_sim(A, B):
       return dot(A, B)/(norm(A)*norm(B))

def shiftKernel(kernel, newValue):
    for i in range(0, len(kernel) - 1):
        kernel[i] = kernel[i+1]
    kernel[len(kernel) - 1] = newValue