무 작위 경사도 하강 을 위 한 매트릭스 분해 추천 알고리즘(python)

SVD 는 행렬 을 분해 하 는 데 자주 사용 되 는 방법 으로 그 원 리 는 행렬 M 은 행렬 A,B 와 C 를 곱 해서 얻 을 수 있 고 B 는 A 또는 C 와 합병 하면 두 가지 요소 인 M1 과 M2 의 행렬 을 곱 하면 M 을 얻 을 수 있다 는 것 이다.
매트릭스 분해 추천 사상 은 이 를 바탕 으로 모든 user 와 item 의 내 적 feature 로 구 성 된 행렬 을 각각 M1 과 M2 로 표시 하면 내 적 feature 의 곱 하기 M 을 얻 을 수 있다.따라서 우 리 는 기 존 데이터(user 가 item 에 대한 점수)를 이용 하여 무 작위 경사도 가 떨 어 지 는 방법 으로 user 와 item 이 가장 가능 한 feature 에 대응 하 는 M1 과 M2(모든 user 와 모든 item 의 내 적 속성 을 얻 는 것 과 같다)를 계산 하면 feature 간 의 내 적 을 통 해 user 가 지나치게 하지 않 은 item 의 점 수 를 얻 을 수 있다.
본 고 에서 사용 한 데 이 터 는 movielens 의 데이터 이 고 스스로 train 과 test 로 절단 되 었 으 나 데이터 의 양 이 많 기 때문에 모든 데 이 터 를 사용 하지 않 았 습 니 다.
코드 는 다음 과 같 습 니 다:

# -*- coding: utf-8 -*-
"""
Created on Mon Oct 9 19:33:00 2017
@author: wjw
"""
import pandas as pd
import numpy as np
import os
 
def difference(left,right,on): #   dataframe   
 df = pd.merge(left,right,how='left',on=on) #  on             
 left_columns = left.columns
 col_y = df.columns[-1] #       
 df = df[df[col_y].isnull()]#  boolean list
 df = df.iloc[:,0:left_columns.size]#               column
 df.columns = left_columns #     columns
 return df
 
def readfile(filepath): #    ,           
 
 pwd = os.getcwd()#           
 os.chdir(os.path.dirname(filepath))
 #os.path.dirname()  filepath     ;chdir()   filepath   
 initialData = pd.read_csv(os.path.basename(filepath))
 #basename()           
 os.chdir(pwd)#         
 predData = initialData.iloc[:,0:3] #         
 newIndexData = predData.drop_duplicates()
 trainData = newIndexData.sample(axis=0,frac = 0.1) #90%        
 testData = difference(newIndexData,trainData,['userId','movieId']).sample(axis=0,frac=0.1)
 return trainData,testData
 
def getmodel(train):
 slowRate = 0.99
 preRmse = 10000000.0
 max_iter = 100
 features = 3
 lamda = 0.2
 gama = 0.01 #         ,      
 user = pd.DataFrame(train.userId.drop_duplicates(),columns=['userId']).reset_index(drop=True) #    dataFrame        ,drop=True   
 
 movie = pd.DataFrame(train.movieId.drop_duplicates(),columns=['movieId']).reset_index(drop=True)
 userNum = user.count().loc['userId'] #671
 movieNum = movie.count().loc['movieId'] 
 userFeatures = np.random.rand(userNum,features) #  user movie       
 movieFeatures = np.random.rand(movieNum,features)
 #    user   movie 3 feature
 userFeaturesFrame =user.join(pd.DataFrame(userFeatures,columns = ['f1','f2','f3']))
 movieFeaturesFrame =movie.join(pd.DataFrame(movieFeatures,columns= ['f1','f2','f3']))
 userFeaturesFrame = userFeaturesFrame.set_index('userId')
 movieFeaturesFrame = movieFeaturesFrame.set_index('movieId') #    index
 
 for i in range(max_iter): 
  rmse = 0
  n = 0
  for index,row in user.iterrows():
   uId = row.userId
   userFeature = userFeaturesFrame.loc[uId] #  userFeatureFrame   uId feature
 
   u_m = train[train['userId'] == uId] #   train userId    movieId data
   for index,row in u_m.iterrows(): 
    u_mId = int(row.movieId)
    realRating = row.rating
    movieFeature = movieFeaturesFrame.loc[u_mId] 
 
    eui = realRating-np.dot(userFeature,movieFeature)
    rmse += pow(eui,2)
    n += 1
    userFeaturesFrame.loc[uId] += gama * (eui*movieFeature-lamda*userFeature) 
    movieFeaturesFrame.loc[u_mId] += gama*(eui*userFeature-lamda*movieFeature)
  nowRmse = np.sqrt(rmse*1.0/n)
  print('step:%f,rmse:%f'%((i+1),nowRmse))
  if nowRmse<preRmse:
   preRmse = nowRmse
  elif nowRmse<0.5:
   break
  elif nowRmse-preRmse<=0.001:
   break
  gama*=slowRate
 return userFeaturesFrame,movieFeaturesFrame
 
def evaluate(userFeaturesFrame,movieFeaturesFrame,test):
 test['predictRating']='NAN' #     
 
 for index,row in test.iterrows(): 
  
  print(index)
  userId = row.userId
  movieId = row.movieId
  if userId not in userFeaturesFrame.index or movieId not in movieFeaturesFrame.index:
   continue
  userFeature = userFeaturesFrame.loc[userId]
  movieFeature = movieFeaturesFrame.loc[movieId]
  test.loc[index,'predictRating'] = np.dot(userFeature,movieFeature) #         
  
 return test 
 
if __name__ == "__main__":
 filepath = r"E:\  \   \    \ml-latest-small\ratings.csv"
 train,test = readfile(filepath)
 userFeaturesFrame,movieFeaturesFrame = getmodel(train)
 result = evaluate(userFeaturesFrame,movieFeaturesFrame,test)
test 에서 얻 은 결 과 는:

NAN 은 트 레이 닝 에 없 는 데이터 입 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기