diff --git a/AI常用函数说明.md b/AI常用函数说明.md
new file mode 100644
index 00000000..e35c1464
--- /dev/null
+++ b/AI常用函数说明.md
@@ -0,0 +1,134 @@
+# AI常用函数说明
+
+## numpy 相关
+
+> from numpy import random, mat, eye
+
+```py
+'''
+# NumPy 矩阵和数组的区别
+NumPy存在2中不同的数据类型:
+ 1. 矩阵 matrix
+ 2. 数组 array
+相似点:
+ 都可以处理行列表示的数字元素
+不同点:
+ 1. 2个数据类型上执行相同的数据运算可能得到不同的结果。
+ 2. NumPy函数库中的 matrix 与 MATLAB中 matrices 等价。
+'''
+from numpy import random, mat, eye
+
+# 生成一个 4*4 的随机数组
+randArray = random.rand(4, 4)
+# 转化关系, 数组转化为矩阵
+randMat = mat(randArray)
+'''
+.I 表示对矩阵求逆(可以利用矩阵的初等变换)
+ 意义: 逆矩阵是一个判断相似性的工具。逆矩阵A与列向量p相乘后,将得到列向量q,q的第i个分量表示p与A的第i个列向量的相似度。
+ 参考案例链接:
+ https://www.zhihu.com/question/33258489
+ http://blog.csdn.net/vernice/article/details/48506027
+.T 表示对矩阵转置(行列颠倒)
+ * 等同于: .transpose()
+.A 返回矩阵基于的数组
+ 参考案例链接:
+ http://blog.csdn.net/qq403977698/article/details/47254539
+'''
+invRandMat = randMat.I
+TraRandMat = randMat.T
+ArrRandMat = randMat.A
+# 输出结果
+print('randArray=(%s) \n' % type(randArray), randArray)
+print('randMat=(%s) \n' % type(randMat), randMat)
+print('invRandMat=(%s) \n' % type(invRandMat), invRandMat)
+print('TraRandMat=(%s) \n' % type(TraRandMat), TraRandMat)
+print('ArrRandMat=(%s) \n' % type(ArrRandMat), ArrRandMat)
+# 矩阵和逆矩阵 进行求积 (单位矩阵,对角线都为1嘛,理论上4*4的矩阵其他的都为0)
+myEye = randMat*invRandMat
+# 误差
+print(myEye - eye(4))
+```
+
+> np.dot
+
+```py
+import numpy as np
+
+a = np.array([2, 3])
+b = np.array([4, 5])
+np.dot(a, b, out=None) #该函数的作用是获取两个元素a,b的乘积
+
+Out[1]: 23 = 2*4 + 3*5
+
+a = np.array([2, 3, 4])
+b = np.array([5, 6, 7])
+np.dot(a, b, out=None) #该函数的作用是获取两个元素a,b的乘积
+
+Out[2]: 56 = 2*5 + 3*6 + 4*7
+```
+
+> array sum/mean
+
+```py
+import numpy as np
+
+# ---- sum ---- #
+a = np.array([[2, 3, 4], [2, 3, 4]])
+
+# 纵向求和: 0 表示某一列所有的行求和
+a.sum(axis=0)
+Out[6]: array([4, 6, 8])
+
+# 横向求和: 1 表示某一行所有的列求和
+a.sum(axis=1)
+Out[7]: array([9, 9])
+
+
+# ---- mean ---- #
+a = np.array([[2, 3, 4], [12, 13, 14]])
+
+# 纵向求平均: 0 表示某一列所有的行求和
+a.mean(axis=0)
+Out[13]: array([7., 8., 9.])
+
+# 横向求平均: 1 表示某一行所有的列求平均
+a.mean(axis=1)
+Out[14]: array([ 3., 13.])
+
+```
+
+> np.newaxis
+
+* numpy 添加新的维度: newaxis(可以给原数组增加一个维度)
+
+```py
+import numpy as np
+
+In [59]: x = np.random.randint(1, 8, size=(2, 3, 4))
+In [60]: y = x[:, np.newaxis, :, :]
+In [61]: Z = x[ :, :, np.newaxis, :]
+
+In [62]: x. shape
+Out[62]: (2, 3, 4)
+
+In [63]: y. shape
+Out[63]: (2, 1, 3, 4)
+
+In [64]: z. shape
+Out [64]: (2, 3, 1, 4)
+```
+
+## keras 相关
+
+> from keras.preprocessing.sequence import pad_sequences
+
+```python
+from keras.preprocessing.sequence import pad_sequences
+
+
+# padding: pre(默认) 向前补充0 post 向后补充0
+# truncating: 文本超过 pad_num, pre(默认) 删除前面 post 删除后面
+x = [[1,2,3,4,5]]
+x_train = pad_sequences(x, maxlen=pad_num, value=0, padding='post', truncating="post")
+print("--- ", x_train[0][:20])
+```
diff --git a/README.md b/README.md
index a23c9e5f..fcb46b5c 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@
* 面试求职:
* 机器学习实战:
* NLP教学视频:
+* **AI常用函数说明**:
## 1.机器学习 - 基础
diff --git a/src/py3.x/ml/16.RecommenderSystems/RS-sklearn-rating.py b/src/py3.x/ml/16.RecommenderSystems/RS-sklearn-rating.py
deleted file mode 100644
index 64a58e9e..00000000
--- a/src/py3.x/ml/16.RecommenderSystems/RS-sklearn-rating.py
+++ /dev/null
@@ -1,190 +0,0 @@
-#!/usr/bin/python
-# coding:utf8
-
-from __future__ import print_function
-import sys
-import math
-from operator import itemgetter
-
-import numpy as np
-import pandas as pd
-from scipy.sparse.linalg import svds
-from sklearn import cross_validation as cv
-from sklearn.metrics import mean_squared_error
-from sklearn.metrics.pairwise import pairwise_distances
-
-
-def splitData(dataFile, test_size):
- # 加载数据集
- header = ['user_id', 'item_id', 'rating', 'timestamp']
- df = pd.read_csv(dataFile, sep='\t', names=header)
-
- n_users = df.user_id.unique().shape[0]
- n_items = df.item_id.unique().shape[0]
-
- print('Number of users = ' + str(n_users) + ' | Number of movies = ' +
- str(n_items))
- train_data, test_data = cv.train_test_split(df, test_size=test_size)
- print("数据量: ", len(train_data), len(test_data))
- return df, n_users, n_items, train_data, test_data
-
-
-def calc_similarity(n_users, n_items, train_data, test_data):
- # 创建用户产品矩阵,针对测试数据和训练数据,创建两个矩阵:
- train_data_matrix = np.zeros((n_users, n_items))
- for line in train_data.itertuples():
- train_data_matrix[line[1] - 1, line[2] - 1] = line[3]
- test_data_matrix = np.zeros((n_users, n_items))
- for line in test_data.itertuples():
- test_data_matrix[line[1] - 1, line[2] - 1] = line[3]
-
- # 使用sklearn的pairwise_distances函数来计算余弦相似性。
- print("1:", np.shape(train_data_matrix)) # 行: 人,列: 电影
- print("2:", np.shape(train_data_matrix.T)) # 行: 电影,列: 人
-
- user_similarity = pairwise_distances(train_data_matrix, metric="cosine")
- item_similarity = pairwise_distances(train_data_matrix.T, metric="cosine")
-
- print('开始统计流行item的数量...', file=sys.stderr)
- item_popular = {}
- # 统计在所有的用户中,不同电影的总出现次数
- for i_index in range(n_items):
- if np.sum(train_data_matrix[:, i_index]) != 0:
- item_popular[i_index] = np.sum(train_data_matrix[:, i_index] != 0)
- # print "pop=", i_index, self.item_popular[i_index]
-
- # save the total number of items
- item_count = len(item_popular)
- print('总共流行item数量 = %d' % item_count, file=sys.stderr)
-
- return train_data_matrix, test_data_matrix, user_similarity, item_similarity, item_popular
-
-
-def predict(rating, similarity, type='user'):
- print(type)
- print("rating=", np.shape(rating))
- print("similarity=", np.shape(similarity))
- if type == 'user':
- # 求出每一个用户,所有电影的综合评分(axis=0 表示对列操作, 1表示对行操作)
- # print "rating=", np.shape(rating)
- mean_user_rating = rating.mean(axis=1)
- # np.newaxis参考地址: http://blog.csdn.net/xtingjie/article/details/72510834
- # print "mean_user_rating=", np.shape(mean_user_rating)
- # print "mean_user_rating.newaxis=", np.shape(mean_user_rating[:, np.newaxis])
- rating_diff = (rating - mean_user_rating[:, np.newaxis])
- # print "rating=", rating[:3, :3]
- # print "mean_user_rating[:, np.newaxis]=", mean_user_rating[:, np.newaxis][:3, :3]
- # print "rating_diff=", rating_diff[:3, :3]
-
- # 均分 + 人-人-距离(943, 943)*人-电影-评分diff(943, 1682)=结果-人-电影(每个人对同一电影的综合得分)(943, 1682) 再除以 个人与其他人总的距离 = 人-电影综合得分
- pred = mean_user_rating[:, np.newaxis] + similarity.dot(
- rating_diff) / np.array([np.abs(similarity).sum(axis=1)]).T
- elif type == 'item':
- # 综合打分: 人-电影-评分(943, 1682)*电影-电影-距离(1682, 1682)=结果-人-电影(各个电影对同一电影的综合得分)(943, 1682) / 再除以 电影与其他电影总的距离 = 人-电影综合得分
- pred = rating.dot(similarity) / np.array(
- [np.abs(similarity).sum(axis=1)])
- return pred
-
-
-def rmse(prediction, ground_truth):
- prediction = prediction[ground_truth.nonzero()].flatten()
- ground_truth = ground_truth[ground_truth.nonzero()].flatten()
- return math.sqrt(mean_squared_error(prediction, ground_truth))
-
-
-def evaluate(prediction, item_popular, name):
- hit = 0
- rec_count = 0
- test_count = 0
- popular_sum = 0
- all_rec_items = set()
- for u_index in range(n_users):
- items = np.where(train_data_matrix[u_index, :] == 0)[0]
- pre_items = sorted(
- dict(zip(items, prediction[u_index, items])).items(),
- key=itemgetter(1),
- reverse=True)[:20]
- test_items = np.where(test_data_matrix[u_index, :] != 0)[0]
-
- # 对比测试集和推荐集的差异 item, w
- for item, _ in pre_items:
- if item in test_items:
- hit += 1
- all_rec_items.add(item)
-
- # 计算用户对应的电影出现次数log值的sum加和
- if item in item_popular:
- popular_sum += math.log(1 + item_popular[item])
-
- rec_count += len(pre_items)
- test_count += len(test_items)
-
- precision = hit / (1.0 * rec_count)
- recall = hit / (1.0 * test_count)
- coverage = len(all_rec_items) / (1.0 * len(item_popular))
- popularity = popular_sum / (1.0 * rec_count)
- print('%s: precision=%.4f \t recall=%.4f \t coverage=%.4f \t popularity=%.4f' % (
- name, precision, recall, coverage, popularity), file=sys.stderr)
-
-
-def recommend(u_index, prediction):
- items = np.where(train_data_matrix[u_index, :] == 0)[0]
- pre_items = sorted(
- dict(zip(items, prediction[u_index, items])).items(),
- key=itemgetter(1),
- reverse=True)[:10]
- test_items = np.where(test_data_matrix[u_index, :] != 0)[0]
-
- print('原始结果: ', test_items)
- print('推荐结果: ', [key for key, value in pre_items])
-
-
-if __name__ == "__main__":
-
- # 基于内存的协同过滤
- # ...
- # 拆分数据集
- # http://files.grouplens.org/datasets/movielens/ml-100k.zip
- dataFile = 'data/16.RecommenderSystems/ml-100k/u.data'
- df, n_users, n_items, train_data, test_data = splitData(
- dataFile, test_size=0.25)
-
- # 计算相似度
- train_data_matrix, test_data_matrix, user_similarity, item_similarity, item_popular = calc_similarity(
- n_users, n_items, train_data, test_data)
-
- item_prediction = predict(train_data_matrix, item_similarity, type='item')
- user_prediction = predict(train_data_matrix, user_similarity, type='user')
-
- # 评估: 均方根误差
- print(
- 'Item based CF RMSE: ' + str(rmse(item_prediction, test_data_matrix)))
- print(
- 'User based CF RMSE: ' + str(rmse(user_prediction, test_data_matrix)))
-
- # 基于模型的协同过滤
- # ...
- # 计算MovieLens数据集的稀疏度 (n_users,n_items 是常量,所以,用户行为数据越少,意味着信息量少;越稀疏,优化的空间也越大)
- sparsity = round(1.0 - len(df) / float(n_users * n_items), 3)
- print('The sparsity level of MovieLen100K is ' + str(sparsity * 100) + '%')
-
- # 计算稀疏矩阵的最大k个奇异值/向量
- u, s, vt = svds(train_data_matrix, k=15)
- s_diag_matrix = np.diag(s)
- svd_prediction = np.dot(np.dot(u, s_diag_matrix), vt)
- print("svd-shape:", np.shape(svd_prediction))
- print(
- 'Model based CF RMSE: ' + str(rmse(svd_prediction, test_data_matrix)))
- """
- 在信息量相同的情况下,矩阵越小,那么携带的信息越可靠。
- 所以: user-cf 推荐效果高于 item-cf; 而svd分解后,发现15个维度效果就能达到90%以上,所以信息更可靠,效果也更好。
- item-cf: 1682
- user-cf: 943
- svd: 15
- """
- evaluate(item_prediction, item_popular, 'item')
- evaluate(user_prediction, item_popular, 'user')
- evaluate(svd_prediction, item_popular, 'svd')
-
- # 推荐结果
- recommend(1, svd_prediction)
diff --git a/tutorials/RecommenderSystems/rs_rating_demo.py b/tutorials/RecommenderSystems/rs_rating_demo.py
new file mode 100644
index 00000000..c2c33de4
--- /dev/null
+++ b/tutorials/RecommenderSystems/rs_rating_demo.py
@@ -0,0 +1,259 @@
+#!/usr/bin/python
+# coding:utf8
+from __future__ import print_function
+import sys
+import math
+from operator import itemgetter
+
+import numpy as np
+import pandas as pd
+from scipy.sparse.linalg import svds
+from sklearn import model_selection as cv
+from sklearn.metrics import mean_squared_error
+from sklearn.metrics.pairwise import pairwise_distances
+from middleware.utils import TimeStat, Chart
+"""
+推荐系统: Item CF/User CF/SVD 对比
+"""
+
+
+def splitData(dataFile, test_size):
+ # 加载数据集 (用户ID, 电影ID, 评分, 时间戳)
+ header = ['user_id', 'item_id', 'rating', 'timestamp']
+ df = pd.read_csv(dataFile, sep='\t', names=header)
+
+ n_users = df.user_id.unique().shape[0]
+ n_items = df.item_id.unique().shape[0]
+
+ print('>>> 本数据集包含: 总用户数 = %s | 总电影数 = %s' % (n_users, n_items) )
+ train_data, test_data = cv.train_test_split(df, test_size=test_size)
+ print(">>> 训练:测试 = %s:%s = %s:%s" % (len(train_data), len(test_data), 1-test_size, test_size))
+ return df, n_users, n_items, train_data, test_data
+
+
+def calc_similarity(n_users, n_items, train_data, test_data):
+ # 创建用户产品矩阵,针对测试数据和训练数据,创建两个矩阵:
+ """
+ line: Pandas(Index=93661, user_id=624, item_id=750, rating=4, timestamp=891961163)
+ """
+ train_data_matrix = np.zeros((n_users, n_items))
+ for line in train_data.itertuples():
+ train_data_matrix[line[1] - 1, line[2] - 1] = line[3]
+
+ test_data_matrix = np.zeros((n_users, n_items))
+ for line in test_data.itertuples():
+ test_data_matrix[line[1] - 1, line[2] - 1] = line[3]
+
+ print("1:", np.shape(train_data_matrix)) # 行: 人 | 列: 电影
+ print("2:", np.shape(train_data_matrix.T)) # 行: 电影 | 列: 人
+
+ # 使用sklearn的 pairwise_distances 计算向量距离,cosine来计算余弦距离,越小越相似
+ user_similarity = pairwise_distances(train_data_matrix, metric="cosine")
+ item_similarity = pairwise_distances(train_data_matrix.T, metric="cosine")
+ # print("<<< %s \n %s" % (np.shape(user_similarity), user_similarity) )
+ # print("<<< %s \n %s" % (np.shape(item_similarity), item_similarity) )
+
+ print('开始统计流行item的数量...', file=sys.stderr)
+ item_popular = {}
+ # 统计同一个电影,观看的总人数(也就是所谓的流行度!)
+ for i_index in range(n_items):
+ if np.sum(train_data_matrix[:, i_index]) != 0:
+ item_popular[i_index] = np.sum(train_data_matrix[:, i_index] != 0)
+
+ # save the total number of items
+ item_count = len(item_popular)
+ print('总共流行 item 数量 = %d' % item_count, file=sys.stderr)
+ return train_data_matrix, test_data_matrix, user_similarity, item_similarity, item_popular
+
+
+def predict(rating, similarity, type='user'):
+ """
+ :param rating: 训练数据
+ :param similarity: 向量距离
+ :return:
+ """
+ print("+++ %s" % type)
+ print(" rating=", np.shape(rating))
+ print(" similarity=", np.shape(similarity))
+ if type == 'item':
+ """
+ 综合打分:
+ rating.dot(similarity) 表示:
+ 某1个人所有的电影组合 X ·电影*电影·距离(第1列都是关于第1部电影和其他的电影的距离)中,计算出 第一个人对第1/2/3部电影的 总评分 1*n
+ 某2个人所有的电影组合 X ·电影*电影·距离(第1列都是关于第1部电影和其他的电影的距离)中,计算出 第一个人对第1/2/3部电影的 总评分 1*n
+ ...
+ 某n个人所有的电影组合 X ·电影*电影·距离(第1列都是关于第1部电影和其他的电影的距离)中,计算出 第一个人对第1/2/3部电影的 总评分 1*n
+ = 人-电影-评分(943, 1682) * 电影-电影-距离(1682, 1682)
+ = 人-电影-总评分距离(943, 1682)
+
+ np.array([np.abs(similarity).sum(axis=1)]) 表示: 横向求和: 1 表示某一行所有的列求和
+ 第1列表示:某个A电影,对于所有电影计算出A的总距离
+ 第2列表示:某个B电影,对于所有电影的综出B的总距离
+ ...
+ 第n列表示:某个N电影,对于所有电影的综出N的总距离
+ = 每一个电影的总距离 (1, 1682)
+
+ pred = 人-电影-平均评分 (943, 1682)
+ """
+ pred = rating.dot(similarity) / np.array([np.abs(similarity).sum(axis=1)])
+ elif type == 'user':
+ # 每个样本上减去数据的统计平均值可以移除共同的部分,凸显个体差异。
+
+ # 求出每一个用户,所有电影的综合评分
+ # 横向求平均: 1 表示某一行所有的列求平均
+ mean_user_rating = rating.mean(axis=1)
+ # numpy中包含的 newaxis 可以给原数组增加一个维度
+ rating_diff = (rating - mean_user_rating[:, np.newaxis])
+
+ # 均分 +
+ # 人-人-距离(943, 943)*人-电影-评分diff(943, 1682)=结果-人-电影(每个人对同一电影的综合得分)(943, 1682) 再除以 个人与其他人总的距离 = 人-电影综合得分
+ """
+ 综合打分:
+ similarity.dot(rating_diff) 表示:
+ 第1列:第1个人与其他人的相似度 * 人与电影的相似度,得到 第1个人对第1/2/3列电影的 总得分 1*n
+ 第2列:第2个人与其他人的相似度 * 人与电影的相似度,得到 第2个人对第1/2/3列电影的 总得分 1*n
+ ...
+ 第n列:第n个人与其他人的相似度 * 人与电影的相似度,得到 第n个人对第1/2/3列电影的 总得分 1*n
+ = 人-人-距离(943, 943) * 人-电影-评分(943, 1682)
+ = 人-电影-总评分距离(943, 1682)
+
+ np.array([np.abs(similarity).sum(axis=1)]) 表示: 横向求和: 1 表示某一行所有的列求和
+ 第1列表示:第A个人,对于所有人计算出A的总距离
+ 第2列表示:第B个人,对于所有人计算出B的总距离
+ ...
+ 第n列表示:第N个人,对于所有人计算出N的总距离
+ = 每一个电影的总距离 (1, 943)
+
+ pred = 均值 + 人-电影-平均评分 (943, 1682)
+ """
+ pred = mean_user_rating[:, np.newaxis] + similarity.dot(rating_diff) / np.array([np.abs(similarity).sum(axis=1)]).T
+
+ return pred
+
+
+def rmse(prediction, ground_truth):
+ prediction = prediction[ground_truth.nonzero()].flatten()
+ ground_truth = ground_truth[ground_truth.nonzero()].flatten()
+ return math.sqrt(mean_squared_error(prediction, ground_truth))
+
+
+def evaluate(prediction, item_popular, name):
+ hit = 0
+ rec_count = 0
+ test_count = 0
+ popular_sum = 0
+ all_rec_items = set()
+ for u_index in range(n_users):
+ items = np.where(train_data_matrix[u_index, :] == 0)[0]
+ pre_items = sorted(
+ dict(zip(items, prediction[u_index, items])).items(),
+ key=itemgetter(1),
+ reverse=True)[:20]
+ test_items = np.where(test_data_matrix[u_index, :] != 0)[0]
+
+ # 对比测试集和推荐集的差异 item, w
+ for item, _ in pre_items:
+ if item in test_items:
+ hit += 1
+ all_rec_items.add(item)
+
+ # popular_sum是对所有的item的流行度进行加和
+ if item in item_popular:
+ popular_sum += math.log(1 + item_popular[item])
+
+ rec_count += len(pre_items)
+ test_count += len(test_items)
+
+ precision = hit / (1.0 * rec_count)
+ # 召回率,相对于测试推荐集合的数据
+ recall = hit / (1.0 * test_count)
+ # 覆盖率,相对于训练集合的数据
+ coverage = len(all_rec_items) / (1.0 * len(item_popular))
+ popularity = popular_sum / (1.0 * rec_count)
+ print('--- %s: precision=%.4f \t recall=%.4f \t coverage=%.4f \t popularity=%.4f' % (
+ name, precision, recall, coverage, popularity), file=sys.stderr)
+
+
+def recommend(u_index, prediction):
+ items = np.where(train_data_matrix[u_index, :] == 0)[0]
+ pre_items = sorted(
+ dict(zip(items, prediction[u_index, items])).items(),
+ key=itemgetter(1),
+ reverse=True)[:10]
+ test_items = np.where(test_data_matrix[u_index, :] != 0)[0]
+
+ result = [key for key, value in pre_items]
+ result.sort(reverse=False)
+ print('原始结果(%s): %s' % (len(test_items), test_items) )
+ print('推荐结果(%s): %s' % (len(result), result) )
+
+
+def main():
+ global n_users, train_data_matrix, test_data_matrix
+ # 基于内存的协同过滤
+ # ...
+ # 拆分数据集
+ # http://files.grouplens.org/datasets/movielens/ml-100k.zip
+ path_root = "/Users/jiangzl/work/data/机器学习"
+ dataFile = '%s/16.RecommenderSystems/ml-100k/u.data' % path_root
+
+ df, n_users, n_items, train_data, test_data = splitData(dataFile, test_size=0.25)
+
+ # 计算相似度
+ train_data_matrix, test_data_matrix, user_similarity, item_similarity, item_popular = calc_similarity(
+ n_users, n_items, train_data, test_data)
+
+ item_prediction = predict(train_data_matrix, item_similarity, type='item')
+ user_prediction = predict(train_data_matrix, user_similarity, type='user')
+
+ # # 评估: 均方根误差
+ print('>>> Item based CF RMSE: ' + str(rmse(item_prediction, test_data_matrix)))
+ print('>>> User based CF RMSE: ' + str(rmse(user_prediction, test_data_matrix)))
+
+ # 基于模型的协同过滤
+ # ...
+ # 计算MovieLens数据集的稀疏度 (n_users,n_items 是常量,所以,用户行为数据越少,意味着信息量少;越稀疏,优化的空间也越大)
+ sparsity = round(1.0 - len(df) / float(n_users * n_items), 3)
+ print('\nMovieLen100K的稀疏度: %s%%\n' % (sparsity * 100))
+
+ # # 计算稀疏矩阵的最大k个奇异值/向量
+ # minrmse = math.inf
+ # index = 1
+ # for k in range(1, 30, 1):
+ # u, s, vt = svds(train_data_matrix, k=k)
+ # # print(">>> ", s)
+ # s_diag_matrix = np.diag(s)
+ # svd_prediction = np.dot(np.dot(u, s_diag_matrix), vt)
+ # r_rmse = rmse(svd_prediction, test_data_matrix)
+ # if r_rmse < minrmse:
+ # index = k
+ # minrmse = r_rmse
+
+ index = 11
+ minrmse = 2.6717213264389765
+ u, s, vt = svds(train_data_matrix, k=index)
+ # print(">>> ", s)
+ s_diag_matrix = np.diag(s)
+ svd_prediction = np.dot(np.dot(u, s_diag_matrix), vt)
+ r_rmse = rmse(svd_prediction, test_data_matrix)
+ print("+++ k=%s, svd-shape: %s" % (index, np.shape(svd_prediction)) )
+ print('>>> Model based CF RMSE: %s\n' % minrmse)
+ # """
+ # 在信息量相同的情况下,矩阵越小,那么携带的信息越可靠。
+ # 所以: user-cf 推荐效果高于 item-cf; 而svd分解后,发现15个维度效果就能达到90%以上,所以信息更可靠,效果也更好。
+ # item-cf: 1682
+ # user-cf: 943
+ # svd: 15
+ # """
+ evaluate(item_prediction, item_popular, 'item')
+ evaluate(user_prediction, item_popular, 'user')
+ evaluate(svd_prediction, item_popular, 'svd')
+
+ # 推荐结果
+ # recommend(1, item_prediction)
+ # recommend(1, user_prediction)
+ recommend(1, svd_prediction)
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file