mirror of
https://github.com/apachecn/ailearning.git
synced 2026-05-07 22:24:18 +08:00
@@ -201,6 +201,8 @@ def pca(dataMat, topNfeat=9999999):
|
||||
return lowDDataMat, reconMat
|
||||
```
|
||||
|
||||
[完整代码地址](https://github.com/apachecn/MachineLearning/blob/master/src/python/13.PCA/pca.py): <https://github.com/apachecn/MachineLearning/blob/master/src/python/13.PCA/pca.py>
|
||||
|
||||
### 要点补充
|
||||
|
||||
```
|
||||
|
||||
@@ -155,7 +155,114 @@ def loadExData2():
|
||||
|
||||
> 分析数据: 暂时不需要
|
||||
|
||||
> 使用算法: 通过调用 recommend() 函数进行推荐
|
||||
> 训练算法: 通过调用 recommend() 函数进行推荐
|
||||
|
||||
* 基于物品相似度(参考地址:http://www.codeweblog.com/svd-%E7%AC%94%E8%AE%B0/)
|
||||
|
||||

|
||||
|
||||
```python
|
||||
# 基于物品相似度的推荐引擎
|
||||
def standEst(dataMat, user, simMeas, item):
|
||||
"""standEst(计算某用户未评分物品中,以对该物品和其他物品评分的用户的物品相似度,然后进行综合评分)
|
||||
|
||||
Args:
|
||||
dataMat 训练数据集
|
||||
user 用户编号
|
||||
simMeas 相似度计算方法
|
||||
item 未评分的物品编号
|
||||
Returns:
|
||||
ratSimTotal/simTotal 评分(0~5之间的值)
|
||||
"""
|
||||
# 得到数据集中的物品数目
|
||||
n = shape(dataMat)[1]
|
||||
# 初始化两个评分值
|
||||
simTotal = 0.0
|
||||
ratSimTotal = 0.0
|
||||
# 遍历行中的每个物品(对用户评过分的物品进行遍历,并将它与其他物品进行比较)
|
||||
for j in range(n):
|
||||
userRating = dataMat[user, j]
|
||||
# 如果某个物品的评分值为0,则跳过这个物品
|
||||
if userRating == 0:
|
||||
continue
|
||||
# 寻找两个用户都评级的物品
|
||||
# 变量 overLap 给出的是两个物品当中已经被评分的那个元素的索引ID
|
||||
# logical_and 计算x1和x2元素的真值。
|
||||
overLap = nonzero(logical_and(dataMat[:, item].A > 0, dataMat[:, j].A > 0))[0]
|
||||
# 如果相似度为0,则两着没有任何重合元素,终止本次循环
|
||||
if len(overLap) == 0:
|
||||
similarity = 0
|
||||
# 如果存在重合的物品,则基于这些重合物重新计算相似度。
|
||||
else:
|
||||
similarity = simMeas(dataMat[overLap, item], dataMat[overLap, j])
|
||||
# print 'the %d and %d similarity is : %f'(iten,j,similarity)
|
||||
# 相似度会不断累加,每次计算时还考虑相似度和当前用户评分的乘积
|
||||
# similarity 用户相似度, userRating 用户评分
|
||||
simTotal += similarity
|
||||
ratSimTotal += similarity * userRating
|
||||
if simTotal == 0:
|
||||
return 0
|
||||
# 通过除以所有的评分总和,对上述相似度评分的乘积进行归一化,使得最后评分在0~5之间,这些评分用来对预测值进行排序
|
||||
else:
|
||||
return ratSimTotal/simTotal
|
||||
```
|
||||
|
||||
* 基于SVD(参考地址:http://www.codeweblog.com/svd-%E7%AC%94%E8%AE%B0/)
|
||||
|
||||

|
||||
|
||||
```python
|
||||
# 基于SVD的评分估计
|
||||
# 在recommend() 中,这个函数用于替换对standEst()的调用,该函数对给定用户给定物品构建了一个评分估计值
|
||||
def svdEst(dataMat, user, simMeas, item):
|
||||
"""svdEst(计算某用户未评分物品中,以对该物品和其他物品评分的用户的物品相似度,然后进行综合评分)
|
||||
|
||||
Args:
|
||||
dataMat 训练数据集
|
||||
user 用户编号
|
||||
simMeas 相似度计算方法
|
||||
item 未评分的物品编号
|
||||
Returns:
|
||||
ratSimTotal/simTotal 评分(0~5之间的值)
|
||||
"""
|
||||
# 物品数目
|
||||
n = shape(dataMat)[1]
|
||||
# 对数据集进行SVD分解
|
||||
simTotal = 0.0
|
||||
ratSimTotal = 0.0
|
||||
# 奇异值分解
|
||||
# 在SVD分解之后,我们只利用包含了90%能量值的奇异值,这些奇异值会以NumPy数组的形式得以保存
|
||||
U, Sigma, VT = la.svd(dataMat)
|
||||
|
||||
# # 分析 Sigma 的长度取值
|
||||
# analyse_data(Sigma, 20)
|
||||
|
||||
# 如果要进行矩阵运算,就必须要用这些奇异值构建出一个对角矩阵
|
||||
Sig4 = mat(eye(4) * Sigma[: 4])
|
||||
# 利用U矩阵将物品转换到低维空间中,构建转换后的物品(物品+4个主要的特征)
|
||||
xformedItems = dataMat.T * U[:, :4] * Sig4.I
|
||||
# 对于给定的用户,for循环在用户对应行的元素上进行遍历,
|
||||
# 这和standEst()函数中的for循环的目的一样,只不过这里的相似度计算时在低维空间下进行的。
|
||||
for j in range(n):
|
||||
userRating = dataMat[user, j]
|
||||
if userRating == 0 or j == item:
|
||||
continue
|
||||
# 相似度的计算方法也会作为一个参数传递给该函数
|
||||
similarity = simMeas(xformedItems[item, :].T, xformedItems[j, :].T)
|
||||
# for 循环中加入了一条print语句,以便了解相似度计算的进展情况。如果觉得累赘,可以去掉
|
||||
print 'the %d and %d similarity is: %f' % (item, j, similarity)
|
||||
# 对相似度不断累加求和
|
||||
simTotal += similarity
|
||||
# 对相似度及对应评分值的乘积求和
|
||||
ratSimTotal += similarity * userRating
|
||||
if simTotal == 0:
|
||||
return 0
|
||||
else:
|
||||
# 计算估计评分
|
||||
return ratSimTotal/simTotal
|
||||
```
|
||||
|
||||
排序获取最后的推荐结果
|
||||
|
||||
```python
|
||||
# recommend()函数,就是推荐引擎,它默认调用standEst()函数,产生了最高的N个推荐结果。
|
||||
@@ -178,6 +285,9 @@ def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):
|
||||
return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[: N]
|
||||
```
|
||||
|
||||
> 测试 和 使用 该算法,可以自行编写
|
||||
|
||||
[完整代码地址](https://github.com/apachecn/MachineLearning/blob/master/src/python/14.SVD/svdRecommend.py): <https://github.com/apachecn/MachineLearning/blob/master/src/python/14.SVD/svdRecommend.py>
|
||||
|
||||
#### 要点补充
|
||||
|
||||
@@ -201,6 +311,97 @@ def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):
|
||||
|
||||
### 项目案例: 基于 SVD 的图像压缩
|
||||
|
||||
> 收集 并 准备数据
|
||||
|
||||
将文本数据转化为矩阵
|
||||
|
||||
```python
|
||||
# 加载并转换数据
|
||||
def imgLoadData(filename):
|
||||
myl = []
|
||||
# 打开文本文件,并从文件以数组方式读入字符
|
||||
for line in open(filename).readlines():
|
||||
newRow = []
|
||||
for i in range(32):
|
||||
newRow.append(int(line[i]))
|
||||
myl.append(newRow)
|
||||
# 矩阵调入后,就可以在屏幕上输出该矩阵
|
||||
myMat = mat(myl)
|
||||
return myMat
|
||||
```
|
||||
|
||||
> 分析数据: 分析 Sigma 的长度个数
|
||||
|
||||
通常保留矩阵 80% ~ 90% 的能量,就可以得到重要的特征并取出噪声。
|
||||
|
||||
```python
|
||||
def analyse_data(Sigma, loopNum=20):
|
||||
"""analyse_data(分析 Sigma 的长度取值)
|
||||
|
||||
Args:
|
||||
Sigma Sigma的值
|
||||
loopNum 循环次数
|
||||
"""
|
||||
# 总方差的集合(总能量值)
|
||||
Sig2 = Sigma**2
|
||||
SigmaSum = sum(Sig2)
|
||||
for i in range(loopNum):
|
||||
SigmaI = sum(Sig2[:i+1])
|
||||
'''
|
||||
根据自己的业务情况,就行处理,设置对应的 Singma 次数
|
||||
|
||||
通常保留矩阵 80% ~ 90% 的能量,就可以得到重要的特征并取出噪声。
|
||||
'''
|
||||
print '主成分:%s, 方差占比:%s%%' % (format(i+1, '2.0f'), format(SigmaI/SigmaSum*100, '4.2f'))
|
||||
```
|
||||
|
||||
> 使用算法: 对比使用 SVD 前后的数据差异对比,对于存储大家可以试着写写
|
||||
|
||||
```python
|
||||
# 打印矩阵
|
||||
def printMat(inMat, thresh=0.8):
|
||||
# 由于矩阵保护了浮点数,因此定义浅色和深色,遍历所有矩阵元素,当元素大于阀值时打印1,否则打印0
|
||||
for i in range(32):
|
||||
for k in range(32):
|
||||
if float(inMat[i, k]) > thresh:
|
||||
print 1,
|
||||
else:
|
||||
print 0,
|
||||
print ''
|
||||
|
||||
|
||||
# 实现图像压缩,允许基于任意给定的奇异值数目来重构图像
|
||||
def imgCompress(numSV=3, thresh=0.8):
|
||||
"""imgCompress( )
|
||||
|
||||
Args:
|
||||
numSV Sigma长度
|
||||
thresh 判断的阈值
|
||||
"""
|
||||
# 构建一个列表
|
||||
myMat = imgLoadData('input/14.SVD/0_5.txt')
|
||||
|
||||
print "****original matrix****"
|
||||
# 对原始图像进行SVD分解并重构图像e
|
||||
printMat(myMat, thresh)
|
||||
|
||||
# 通过Sigma 重新构成SigRecom来实现
|
||||
# Sigma是一个对角矩阵,因此需要建立一个全0矩阵,然后将前面的那些奇异值填充到对角线上。
|
||||
U, Sigma, VT = la.svd(myMat)
|
||||
# SigRecon = mat(zeros((numSV, numSV)))
|
||||
# for k in range(numSV):
|
||||
# SigRecon[k, k] = Sigma[k]
|
||||
|
||||
# 分析插入的 Sigma 长度
|
||||
analyse_data(Sigma, 20)
|
||||
|
||||
SigRecon = mat(eye(numSV) * Sigma[: numSV])
|
||||
reconMat = U[:, :numSV] * SigRecon * VT[:numSV, :]
|
||||
print "****reconstructed matrix using %d singular values *****" % numSV
|
||||
printMat(reconMat, thresh)
|
||||
```
|
||||
|
||||
[完整代码地址](https://github.com/apachecn/MachineLearning/blob/master/src/python/14.SVD/svdRecommend.py): <https://github.com/apachecn/MachineLearning/blob/master/src/python/14.SVD/svdRecommend.py>
|
||||
|
||||
* * *
|
||||
|
||||
|
||||
BIN
images/14.SVD/基于SVD.png
Normal file
BIN
images/14.SVD/基于SVD.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
images/14.SVD/基于物品相似度.png
Normal file
BIN
images/14.SVD/基于物品相似度.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
32
input/14.SVD/0_5.txt
Executable file
32
input/14.SVD/0_5.txt
Executable file
@@ -0,0 +1,32 @@
|
||||
00000000000000110000000000000000
|
||||
00000000000011111100000000000000
|
||||
00000000000111111110000000000000
|
||||
00000000001111111111000000000000
|
||||
00000000111111111111100000000000
|
||||
00000001111111111111110000000000
|
||||
00000000111111111111111000000000
|
||||
00000000111111100001111100000000
|
||||
00000001111111000001111100000000
|
||||
00000011111100000000111100000000
|
||||
00000011111100000000111110000000
|
||||
00000011111100000000011110000000
|
||||
00000011111100000000011110000000
|
||||
00000001111110000000001111000000
|
||||
00000011111110000000001111000000
|
||||
00000011111100000000001111000000
|
||||
00000001111100000000001111000000
|
||||
00000011111100000000001111000000
|
||||
00000001111100000000001111000000
|
||||
00000001111100000000011111000000
|
||||
00000000111110000000001111100000
|
||||
00000000111110000000001111100000
|
||||
00000000111110000000001111100000
|
||||
00000000111110000000011111000000
|
||||
00000000111110000000111111000000
|
||||
00000000111111000001111110000000
|
||||
00000000011111111111111110000000
|
||||
00000000001111111111111110000000
|
||||
00000000001111111111111110000000
|
||||
00000000000111111111111000000000
|
||||
00000000000011111111110000000000
|
||||
00000000000000111111000000000000
|
||||
@@ -150,11 +150,22 @@ def svdEst(dataMat, user, simMeas, item):
|
||||
# 奇异值分解
|
||||
# 在SVD分解之后,我们只利用包含了90%能量值的奇异值,这些奇异值会以NumPy数组的形式得以保存
|
||||
U, Sigma, VT = la.svd(dataMat)
|
||||
|
||||
# # 分析 Sigma 的长度取值
|
||||
# analyse_data(Sigma, 20)
|
||||
|
||||
# 如果要进行矩阵运算,就必须要用这些奇异值构建出一个对角矩阵
|
||||
Sig4 = mat(eye(4) * Sigma[: 4])
|
||||
# 利用U矩阵将物品转换到低维空间中,构建转换后的物品
|
||||
|
||||
# 利用U矩阵将物品转换到低维空间中,构建转换后的物品(物品+4个主要的特征)
|
||||
xformedItems = dataMat.T * U[:, :4] * Sig4.I
|
||||
# 对于给定的用户,for循环在用户对应行的元素上进行遍历,
|
||||
print 'dataMat', shape(dataMat)
|
||||
print 'U[:, :4]', shape(U[:, :4])
|
||||
print 'Sig4.I', shape(Sig4.I)
|
||||
print 'VT[:4, :]', shape(VT[:4, :])
|
||||
print 'xformedItems', shape(xformedItems)
|
||||
|
||||
# 对于给定的用户,for循环在用户对应行的元素上进行遍历
|
||||
# 这和standEst()函数中的for循环的目的一样,只不过这里的相似度计算时在低维空间下进行的。
|
||||
for j in range(n):
|
||||
userRating = dataMat[user, j]
|
||||
@@ -205,7 +216,41 @@ def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):
|
||||
return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[: N]
|
||||
|
||||
|
||||
def analyse_data(Sigma, loopNum=20):
|
||||
"""analyse_data(分析 Sigma 的长度取值)
|
||||
|
||||
Args:
|
||||
Sigma Sigma的值
|
||||
loopNum 循环次数
|
||||
"""
|
||||
# 总方差的集合(总能量值)
|
||||
Sig2 = Sigma**2
|
||||
SigmaSum = sum(Sig2)
|
||||
for i in range(loopNum):
|
||||
SigmaI = sum(Sig2[:i+1])
|
||||
'''
|
||||
根据自己的业务情况,就行处理,设置对应的 Singma 次数
|
||||
|
||||
通常保留矩阵 80% ~ 90% 的能量,就可以得到重要的特征并取出噪声。
|
||||
'''
|
||||
print '主成分:%s, 方差占比:%s%%' % (format(i+1, '2.0f'), format(SigmaI/SigmaSum*100, '4.2f'))
|
||||
|
||||
|
||||
# 图像压缩函数
|
||||
# 加载并转换数据
|
||||
def imgLoadData(filename):
|
||||
myl = []
|
||||
# 打开文本文件,并从文件以数组方式读入字符
|
||||
for line in open(filename).readlines():
|
||||
newRow = []
|
||||
for i in range(32):
|
||||
newRow.append(int(line[i]))
|
||||
myl.append(newRow)
|
||||
# 矩阵调入后,就可以在屏幕上输出该矩阵
|
||||
myMat = mat(myl)
|
||||
return myMat
|
||||
|
||||
|
||||
# 打印矩阵
|
||||
def printMat(inMat, thresh=0.8):
|
||||
# 由于矩阵保护了浮点数,因此定义浅色和深色,遍历所有矩阵元素,当元素大于阀值时打印1,否则打印0
|
||||
@@ -220,25 +265,30 @@ def printMat(inMat, thresh=0.8):
|
||||
|
||||
# 实现图像压缩,允许基于任意给定的奇异值数目来重构图像
|
||||
def imgCompress(numSV=3, thresh=0.8):
|
||||
"""imgCompress( )
|
||||
|
||||
Args:
|
||||
numSV Sigma长度
|
||||
thresh 判断的阈值
|
||||
"""
|
||||
# 构建一个列表
|
||||
myl = []
|
||||
# 打开文本文件,并从文件以数组方式读入字符
|
||||
for line in open('testData/testDigits/0_5.txt').readlines():
|
||||
newRow = []
|
||||
for i in range(32):
|
||||
newRow.append(int(line[i]))
|
||||
myl.append(newRow)
|
||||
# 矩阵调入后,就可以在屏幕上输出该矩阵
|
||||
myMat = mat(myl)
|
||||
myMat = imgLoadData('input/14.SVD/0_5.txt')
|
||||
|
||||
print "****original matrix****"
|
||||
# 对原始图像进行SVD分解并重构图像e
|
||||
printMat(myMat, thresh)
|
||||
|
||||
# 通过Sigma 重新构成SigRecom来实现
|
||||
# Sigma是一个对角矩阵,因此需要建立一个全0矩阵,然后将前面的那些奇异值填充到对角线上。
|
||||
U, Sigma, VT = la.svd(myMat)
|
||||
SigRecon = mat(zeros((numSV, numSV)))
|
||||
for k in range(numSV):
|
||||
SigRecon[k, k] = Sigma[k]
|
||||
# SigRecon = mat(zeros((numSV, numSV)))
|
||||
# for k in range(numSV):
|
||||
# SigRecon[k, k] = Sigma[k]
|
||||
|
||||
# 分析插入的 Sigma 长度
|
||||
analyse_data(Sigma, 20)
|
||||
|
||||
SigRecon = mat(eye(numSV) * Sigma[: numSV])
|
||||
reconMat = U[:, :numSV] * SigRecon * VT[:numSV, :]
|
||||
print "****reconstructed matrix using %d singular values *****" % numSV
|
||||
printMat(reconMat, thresh)
|
||||
|
||||
Reference in New Issue
Block a user