67、矩阵分解的梯度下降求解、随机梯度下降

梯度下降:

import math
import random as rd

def Loss(U, I, D, d):
    loss = 0
    for u, i in D:
        loss += pow(sum([U[u][t]*I[i][t] for t in range(d)])-D[u, i], 2)
    return loss

def step_search(U, dU, I, dI, x, d, D):
    U1 = {u: [U[u][t] + x * dU[u][t] for t in range(d)] for u in U}
    I1 = {i: [I[i][t] + x * dI[i][t] for t in range(d)] for i in I}
    return Loss(U1, I1, D, d)

def mod(dU, dI, d):
    return math.sqrt(sum([dU[u][t]*dU[u][t] for u in dU for t in range(d)])+sum([dI[i][t]*dI[i][t] for i in dI for t in range(d)]))

def Matrix_Decomposition(users, items, M, d, r=0.8, step_min=0.00001):
    U = {u: [rd.random() for t in range(d)] for u in users}
    I = {i: [rd.random() for t in range(d)] for i in items}
    D = {(row[0], row[1]): row[2] for row in M}

    loop = 0
    while True:
        loop += 1
        print("loop: ", loop, "loss: ", Loss(U, I, D, d))
        #负梯度方向
        dU = {u:[-2*sum([(sum([U[u][t1]*I[i][t1] for t1 in range(d)])-D[u, i])*I[i][t] for i in I if (u, i) in D]) for t in range(d)] for u in U}
        dI = {i:[-2*sum([(sum([U[u][t1]*I[i][t1] for t1 in range(d)])-D[u, i])*U[u][t] for u in U if (u, i) in D]) for t in range(d)] for i in I}

        left = 0
        right = 1
        while step_search(U, dU, I, dI, right, d, D) < step_search(U, dU, I, dI, 0, d, D):
            right = right * (2 - r)

        mid1 = left * 2 / 3 + right / 3
        mid2 = left / 3 + right * 2 / 3
        while abs(left - right) * mod(dU, dI, d) > step_min:
            if step_search(U, dU, I, dI, mid1, d, D) < step_search(U, dU, I, dI, mid2, d, D):
                right = mid2
            else:
                left = mid1
            mid1 = left * 2 / 3 + right / 3
            mid2 = left / 3 + right * 2 / 3

        if left * mod(dU, dI, d) < step_min:
            break

        U = {u: [U[u][t] + left * dU[u][t] for t in range(d)] for u in U}
        I = {i: [I[i][t] + left * dI[i][t] for t in range(d)] for i in I}

    print("loop: ", loop, "loss: ", Loss(U, I, D, d))

    return U, I

if __name__ == '__main__':
    users = [1,2,3]
    items = [1, 2, 3]
    M = [[1, 1, 1],
         [2, 1, 0],
         [3, 1, 0],
         [1, 2, 0],
         [2, 2, 1],
         [3, 2, 0],
         [1, 3, 0],
         [2, 3, 0],
         [3, 3, 1]]
    d = 4
    U, I = Matrix_Decomposition(users, items, M, d)

SGD:

import math
import random as rd

def Loss(U, I, D, d):
    loss = 0
    for u, i in D:
        loss += pow(sum([U[u][t]*I[i][t] for t in range(d)])-D[u, i], 2)
    return loss

def step_search(U, dU, I, dI, x, d, D):
    U1 = {u: [U[u][t] + x * dU[u][t] for t in range(d)] for u in U}
    I1 = {i: [I[i][t] + x * dI[i][t] for t in range(d)] for i in I}
    return Loss(U1, I1, D, d)

def mod(dU, dI, d):
    return math.sqrt(sum([dU[u][t]*dU[u][t] for u in dU for t in range(d)])+sum([dI[i][t]*dI[i][t] for i in dI for t in range(d)]))

def Matrix_Decomposition(users, items, M, d, r=0.8, step_min=0.00001, s=0.1):
    U = {u: [rd.random() for t in range(d)] for u in users}
    I = {i: [rd.random() for t in range(d)] for i in items}
    D = {(row[0], row[1]): row[2] for row in M}

    loop = 0
    while True:
        loop += 1
        z0 = Loss(U, I, D, d)
        print("loop: ", loop, "z0: ", z0)
        for u, i in D:
            du = [-2*(sum([U[u][t1]*I[i][t1] for t1 in range(d)])-D[u, i])*I[i][t] for t in range(d)]
            di = [-2*(sum([U[u][t1]*I[i][t1] for t1 in range(d)])-D[u, i])*U[u][t] for t in range(d)]
            u1 = [U[u][t]+s*du[t] for t in range(d)]
            i1 = [I[i][t]+s*di[t] for t in range(d)]
            U[u] = u1
            I[i] = i1

        z1 = Loss(U, I, D, d)
        print("loop: ", loop, "z1: ", z1)

        if abs(z1-z0) < step_min:
            break

    print("loop: ", loop, "loss: ", Loss(U, I, D, d))

    return U, I

if __name__ == '__main__':
    users = [1,2,3]
    items = [1, 2, 3]
    M = [[1, 1, 1],
         [2, 1, 0],
         [3, 1, 0],
         [1, 2, 0],
         [2, 2, 1],
         [3, 2, 0],
         [1, 3, 0],
         [2, 3, 0],
         [3, 3, 1]]
    d = 4
    U, I = Matrix_Decomposition(users, items, M, d)

固定步长:

import math
import random as rd

def Loss(U, I, D, d):
    loss = 0
    for u, i in D:
        loss += pow(sum([U[u][t]*I[i][t] for t in range(d)])-D[u, i], 2)
    return loss

def step_search(U, dU, I, dI, x, d, D):
    U1 = {u: [U[u][t] + x * dU[u][t] for t in range(d)] for u in U}
    I1 = {i: [I[i][t] + x * dI[i][t] for t in range(d)] for i in I}
    return Loss(U1, I1, D, d)

def mod(dU, dI, d):
    return math.sqrt(sum([dU[u][t]*dU[u][t] for u in dU for t in range(d)])+sum([dI[i][t]*dI[i][t] for i in dI for t in range(d)]))

def Matrix_Decomposition(users, items, M, d, r=0.8, step_min=0.00001):
    U = {u: [rd.random() for t in range(d)] for u in users}
    I = {i: [rd.random() for t in range(d)] for i in items}
    D = {(row[0], row[1]): row[2] for row in M}

    loop = 0
    while True:
        loop += 1
        print("loop: ", loop, "loss: ", Loss(U, I, D, d))
        #负梯度方向
        dU = {u:[-2*sum([(sum([U[u][t1]*I[i][t1] for t1 in range(d)])-D[u, i])*I[i][t] for i in I if (u, i) in D]) for t in range(d)] for u in U}
        dI = {i:[-2*sum([(sum([U[u][t1]*I[i][t1] for t1 in range(d)])-D[u, i])*U[u][t] for u in U if (u, i) in D]) for t in range(d)] for i in I}

        left = 0.1

        if left * mod(dU, dI, d) < step_min:
            break

        U = {u: [U[u][t] + left * dU[u][t] for t in range(d)] for u in U}
        I = {i: [I[i][t] + left * dI[i][t] for t in range(d)] for i in I}

    print("loop: ", loop, "loss: ", Loss(U, I, D, d))

    return U, I

if __name__ == '__main__':
    users = [1,2,3]
    items = [1, 2, 3]
    M = [[1, 1, 1],
         [2, 1, 0],
         [3, 1, 0],
         [1, 2, 0],
         [2, 2, 1],
         [3, 2, 0],
         [1, 3, 0],
         [2, 3, 0],
         [3, 3, 1]]
    d = 4
    U, I = Matrix_Decomposition(users, items, M, d)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值