読者です 読者をやめる 読者になる 読者になる

リコメンドコンテストで使ったプログラム

リコメンドコンテスト2009で、データを分析する時に使ったプログラムを置いとく。

特異値分解して、ユーザー行列とワード行列、ユーザーベクトル同士のcosをとったものを出力する。

入力ファイルの形式は横にワード、縦にユーザー、中は検索回数

プログラムは

d.hatena.ne.jp

を参考にさせていただいた。感謝!

このプログラム使って何ら不具合起きても、責任取れません。

#-*-coding:utf-8-*-

import numpy,codecs
from numpy import *
from scipy import linalg

fin = open('user-word.csv','r')
fout = codecs.open('lsi.csv', 'w', 'utf-8')
fouta = codecs.open('user.csv', 'w', 'utf-8')
foutb = codecs.open('word.csv', 'w', 'utf-8')

wordlist = []
userid = []
allcount = []

i = 0
for line in fin:
  lines = line.split(',')
  if i == 0:
    for wordlistword in lines[1:]:
      wordlist.append(unicode(wordlistword,"utf-8"))
  else:
    userid.append(int(lines[0]))
    allcount.append(map(int,lines[1:]))
  i = i + 1

allcountg = array(allcount)
k = len(userid) # 階数
u, sigma, v = linalg.svd(allcountg) # 特異値分解

u = array(u[:, :k])
s = array(linalg.diagsvd(sigma, k, k))
v = array(v[:k, :])

#次元圧縮
z= 0
while (sum(sigma[:z])/sum(sigma))<0.8:
z = z + 1
print z

uu = u[:, :z]
ss = array(linalg.diagsvd(sigma[:z], z, z))
vv = v[:z, :]

assyukuuser = uu
assyukuword = transpose(vv)

i = 0
for userb in assyukuuser:
  fout.write(str(userid[i]))
  for userbb in userb:
    fout.write(",")
    fout.write(str(userbb))
  fout.write("\n")
  i = i + 1

i = 0
for wordb in assyukuword:
  foutb.write(wordlist[i])
  for wordbb in wordb:
  foutb.write(",")
  foutb.write(str(wordbb))
  foutb.write("\n")
  i = i + 1

  for id in userid:
    fouta.write(",")
    fouta.write(str(id))
  fouta.write("\n")

i = 0
for usera in uu:
  lengtha = numpy.linalg.norm(usera)
  fouta.write(str(userid[i]))
  for userb in uu:
    lengthb = numpy.linalg.norm(userb)
    cosab = dot(usera,userb)/(lengtha*lengthb)
    fouta.write(",")
    fouta.write(str(cosab))
  fouta.write("\n")
  i = i + 1