这篇博客会讲到:对书本算法部分代码的理解,和构建01矩阵,训练矩阵,得到物品相似矩阵的过程。以及:在学习这一章节了解到的对pandas的运用。由于电脑有点垃圾,这里我选择了30000条数据写进csv文件方便代码调试
def Jaccard(a, b): # 自定义杰卡德相似系数函数,仅对0-1矩阵有效
return 1.0 * (a * b).sum() / (a + b - a * b).sum()
a,b都是只包含01的一行多列列表,类似[0,1,0,1],[1,1,0,1],ab相乘得到[0,1,0,1],他们的列名就是用户a,用户b,用户c…一行代表一个物品,用户b、用户d喜欢物品A,用户a、b、d喜欢物品B,相乘以后同时喜欢物品A、B的用户才为1,sum作用为计算这个数量。同理,a+b会计算物品A和B被喜欢的总人次,但会把同时喜欢两者的用户计算重复,所以减去ab
def recommend(self, a): # 推荐函数
return np.dot(self.sim, a) * (1 - a)
np.dot(self.sim,a)这是矩阵乘法函数,假设我训练模型是:
[[0 0 1 1 0]
[1 1 1 1 0]
[1 0 0 0 1]]
self.sim返回的类型是p260页的物品相似矩阵,上述矩阵训练完:
[[1. 0.5 0. ]
[0.5 1. 0.2]
[0. 0.2 1. ]]
测试矩阵:
[[0 1]
[0 0]
[1 1]]
其实*(1-a)的作用就是把用户本来喜欢的物品类型除去,这里看对比。测试结果:
[[0. 1. ]
[0.2 0.7]
[1. 1. ]]
乘了以后
[[0. 0. ]
[0.2 0.7]
[0. 0. ]]
#选择107开头网页类型
将用户IP设置成索引
用“\“为标准将网址分割成各种类型,expand=True表示分割的类型变成单独一列,这里不需要
user_array = df[['realIP','fullURL']][df['fullURLId'].str.contains('107')].copy()
user_array.set_index('realIP',inplace=True)
user_array = user_array['fullURL'].str.split(r'/',expand= False)
将划分的类型列表存进大列表,把其中小列表变成字符串类型,方便特征提取
mat = user_array.tolist()
mat = [str(i) for i in mat]
特征提取,特征处理。处理后的数据变成dataframe类型存入文件
from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer()
cv_fit=cv.fit_transform(mat)
User_matrix = pd.DataFrame(cv_fit.toarray(),index=user_array.index,columns=cv.get_feature_names()).T
User_matrix['type'] = User_matrix.index
User_matrix = User_matrix[User_matrix['type'].notnull()]
User_matrix = User_matrix[~User_matrix['type'].str.contains('(http)|(\d+?)|(html)|(www)|(cn)|(lawtime)')]
User_matrix.drop('type',axis=1,inplace=True)
User_matrix.to_csv('./FT.csv',encoding='gbk')
划分训练集并训练模型,测试模型
import pandas as pd
from func_who import Recommender
df = pd.read_csv("./FT.csv",encoding='gbk')
df.set_index('Unnamed: 0',inplace=True)
# df.loc['Row_sum'] = df.apply(lambda x: x.sum())#计算列和并单独生成一列
Re = Recommender()
datas = df.iloc[:,:4800].copy()#取前4800条数据训练,后面的数据用于测试
datas_1 = df.iloc[:,4800:].copy()
data_train = datas.as_matrix()#将dataframe类型数据变成矩阵方便运算
data_test = datas_1.as_matrix()
Re.fit(data_train)
# print(data)
# print(data_1)
result = Re.recommend(data_test)
result = pd.DataFrame(result,index=datas_1.index,columns=datas_1.columns)
result.to_csv('./result.csv',encoding='gbk')#把测试数据和测试结果存进文件
datas_1.to_csv('./test.csv',encoding='gbk')
1、pandas读取一些文件时,会把某些字符串如用户ID当作int类型读取。这时df[列名].str就不能用了,例如str.extract、str.contains、str.split。这时用dtype指定读取类型
data = pd.read_csv("./clear_data.csv",encoding= ‘gbk’,dtype={‘fullURLId’:str})
还有就是str.contains对空值操作时会报错,用的时候一定记得先处理空值。另外几个没注意
2、df[‘列名’].str.split(’’,expand=True),expand能够把分割的字符串重新作为一列
3、当一个列表中有很多小列表时
[x for y in 列表 for x in y]这个表达式能把小列表解开
4、把函数用到dataframe每一个元素的方法,返回bool类型
bool——array = df.applymap(lambda x:“w” in x)
5、User_matrix = User_matrix[~User_matrix[‘type’].str.contains(’(http)’)]
User_matrix = User_matrix[User_matrix[‘type’].str.contains(’(http)’)]
这两个表达式的区别就是多了’~‘这个符号,第一列是选取不包含http的数据,第二列表示选取选择包含http的数据
6、sql = pd.read_sql(‘all_gzdata’, engine, chunksize = 10000)这里返回的sql是生成器对象,可以使用‘sql.__next__按块读取,一次读一块
7、[i for i in sql]一次只能运行一次,如果代码中有两行这个代码,那么第二个代码返回的是空列表
暂时就这些了,实在想不出来了
import pandas as pd
data = pd.read_csv("./clear_data.csv",encoding= 'gbk',dtype={'fullURLId':str})
data = data[data['fullURLId'].str.contains('107')]
sets = data['fullURL'].str.split(r'/',expand= True)
print(sets)
sets = sets.iloc[:,4:]
style = []
for i in sets.columns:
j = sets[sets[i].notnull()]
j = list(j[i][~j[i].str.contains('\.html|\d+?')].unique())
style.append(j)
sets.index = data['realIP']
style = [x for y in style for x in y]
print(style)
print(len(style))
最后欢迎大家一起交流python
人生苦短,我选python
qq交流:2227542337
转载注明出处