Python 正在寻找一种更有效的方法,通过不同行上的信息对CSV进行矢量化
我正在参加一个机器学习比赛,目标是预测客户在给定行程信息的情况下前往超市的行程类型或动机。我有一个以下格式的CSV文件:Python 正在寻找一种更有效的方法,通过不同行上的信息对CSV进行矢量化,python,csv,vector,machine-learning,Python,Csv,Vector,Machine Learning,我正在参加一个机器学习比赛,目标是预测客户在给定行程信息的情况下前往超市的行程类型或动机。我有一个以下格式的CSV文件: TripType,VisitNumber,Weekday,Upc,ScanCount,DepartmentDescription,FinelineNumber 999,5,Friday,68113152929,-1,FINANCIAL SERVICES,1000 30,7,Friday,60538815980,1,SHOES,8931 30,7,Friday,74108110
TripType,VisitNumber,Weekday,Upc,ScanCount,DepartmentDescription,FinelineNumber
999,5,Friday,68113152929,-1,FINANCIAL SERVICES,1000
30,7,Friday,60538815980,1,SHOES,8931
30,7,Friday,7410811099,1,PERSONAL CARE,4504
26,8,Friday,2238403510,2,PAINT AND ACCESSORIES,3565
26,8,Friday,2006613744,2,PAINT AND ACCESSORIES,1017
我采取的第一步是将这些数据转换为特征向量。为此,我将每个分类变量转换为虚拟变量,然后每个向量将是唯一的样本。创建向量的问题是,样本在行上没有分开;您有关于不同行上的样本的数据。例如,在上面,我们有5行,但只有3个样本(5、7和8)。以下是上述样本的特征向量:
'Friday', 68113152929, 60538815980, 7410811099, 2238403510, 2006613744, 'FINANCIAL SERVICES', 'SHOES', 'PERSONAL CARE', 'PAINT AND ACCESSORIES', 1000, 8931, 4504, 3565, 1017, 'Returned'
[ 1. 0. 0. 0. 0. 0. 1. 0. 0. 0. 1. 0. 0. 0. 0. 1.]
[ 1. 0. 1. 1. 0. 0. 0. 1. 1. 0. 0. 1. 1. 0. 0. 0.]
[ 1. 0. 0. 0. 2. 2. 0. 0. 0. 1. 0. 0. 0. 1. 1. 0.]
请注意,我在末尾添加了“Returned”功能(当任何UPC或购买的物品的扫描计数为负数时,这是1)。还有一个带有相应标签的“目标”向量:
[999, 30, 26]
我的问题是如何高效地生成这些向量。我比较快地完成了程序的这一部分,只在我拥有的总数据(约700k行)的一小部分(100-1000行)上测试了我的代码。当我完成程序的其余部分(学习和预测部分)并返回到整个数据时,“矢量化”部分似乎花费了太长的时间。您是否有任何建议来实现这一点(从csv文件获取特征向量)以获得更好的性能
这是我现在使用的代码。如果你想知道我现在在做什么,请看一看。转到“Iter逐行”,直接进入矢量化部分:
import pandas as pd
#Reshape smaller vector by adding zeros to the beginning. Add the vectors but add 0 if there's a value in both vectors other than zero
def vector_add(P, Q):
a = []
for x,y in izip_longest(reversed(P), reversed(Q), fillvalue=0):
if x == 0 or y == 0:
a.append(x+y)
else:
a.append(1)
return a[::-1]
csv_file = open('exp-train', 'rb')
df = pd.read_csv(csv_file)
# Get features
visitnums = df.drop_duplicates(subset='VisitNumber')['VisitNumber']
days = df.drop_duplicates(subset='Weekday')['Weekday']
upcs = df.drop_duplicates(subset='Upc')['Upc']
departments = df.drop_duplicates(subset='DepartmentDescription')['DepartmentDescription']
finenums = df.drop_duplicates(subset='FinelineNumber')['FinelineNumber']
# List to contain all feature vectors
lines = []
# Put in list and put put list in the large list
top_line = []
top_line.append('VisitType')
for day in days:
top_line.append(day)
for upc in upcs:
top_line.append(upc)
for department in departments:
top_line.append(department)
for finenum in finenums:
top_line.append(finenum)
top_line.append('Returned')
lines.append(top_line)
#Iterate by row
counter = 0
#Back variable deal with duplicate samples
back = 'no'
line = []
returned = 0
for i, row in enumerate(df.itertuples()):
#Line2 to deal with duplicate samples
line2 = []
if not back == row[2]:
if not back == 'no':
line.append(returned)
returned = 0
lines.append(line)
line = []
line.append(row[1])
for day in days:
if day == row[3]:
line.append(1)
else:
line.append(0)
for upc in upcs:
if upc == row[4]:
if int(row[5]) < 0:
returned = 1
line.append(0)
else:
line.append(int(row[5]))
else:
line.append(0)
for department in departments:
if department == row[6]:
line.append(1)
else:
line.append(0)
for finenum in finenums:
if finenum == row[7]:
line.append(1)
else:
line.append(0)
else:
for upc in upcs:
if upc == row[4]:
if int(row[5]) < 0:
returned = 1
line2.append(0)
else:
line2.append(int(row[5]))
else:
line2.append(0)
for department in departments:
if department == row[6]:
line2.append(1)
else:
line2.append(0)
for finenum in finenums:
if finenum == row[7]:
line2.append(1)
else:
line2.append(0)
#Deal with multiple samples by adding line, line2 into line
line = vector_add(line, line2)
back = row[2]
if i == (len(df.index) - 1):
line.append(returned)
returned = 0
lines.append(line)
a = time.time()
将熊猫作为pd导入
#通过在开始处添加零来重塑较小的向量。添加向量,但如果两个向量中的值都不是零,则添加0
定义向量_加法(P,Q):
a=[]
对于izip_中的x,y最长(反向(P),反向(Q),填充值=0):
如果x==0或y==0:
a、 附加(x+y)
其他:
a、 附加(1)
返回一个[:-1]
csv_文件=打开('exp-train','rb')
df=pd.read\u csv(csv\u文件)
#获取特征
visitnums=df.drop_duplicates(subset='VisitNumber')['VisitNumber']
days=df.drop_duplicates(subset='Weekday')['Weekday']
upcs=df.drop_duplicates(subset='Upc')['Upc']
departments=df.drop_duplicates(subset='DepartmentDescription')['DepartmentDescription']
finenums=df.drop_重复项(subset='FinelineNumber')['FinelineNumber']
#包含所有特征向量的列表
行=[]
#放入列表并将放入列表放入大列表
顶行=[]
顶行追加('VisitType')
对于以天为单位的天:
顶行追加(天)
对于upc中的upc:
顶行追加(upc)
部门中的部门:
顶行追加(部门)
对于finenum中的finenum:
顶行追加(finenum)
顶行追加('Returned')
行。追加(顶行)
#逐行迭代
计数器=0
#Back变量处理重复样本
后退='否'
行=[]
返回值=0
对于i,枚举中的行(df.itertuples()):
#第2行处理重复样本
第2行=[]
如果不返回==行[2]:
如果未返回==“否”:
行。追加(返回)
返回值=0
行。追加(行)
行=[]
行。追加(第[1]行)
对于以天为单位的天:
如果日期==第[3]行:
行。追加(1)
其他:
行。追加(0)
对于upc中的upc:
如果upc==行[4]:
如果int(第[5]行)小于0:
返回=1
行。追加(0)
其他:
行。追加(int(行[5]))
其他:
行。追加(0)
部门中的部门:
如果部门==行[6]:
行。追加(1)
其他:
行。追加(0)
对于finenum中的finenum:
如果finenum==行[7]:
行。追加(1)
其他:
行。追加(0)
其他:
对于upc中的upc:
如果upc==行[4]:
如果int(第[5]行)小于0:
返回=1
第2行。追加(0)
其他:
第2行追加(int(第[5]行))
其他:
第2行。追加(0)
部门中的部门:
如果部门==行[6]:
第2行。追加(1)
其他:
第2行。追加(0)
对于finenum中的finenum:
如果finenum==行[7]:
第2行。追加(1)
其他:
第2行。追加(0)
#通过在第行中添加第行、第2行来处理多个示例
直线=矢量_添加(直线,直线2)
后排=第[2]排
如果i==(len(df.index)-1):
行。追加(返回)
返回值=0
行。追加(行)
a=时间。时间()
请告诉我是否有更好的方法来解决这个问题。如果我理解正确,您可以简单地创建这样一个公式:
import pandas as pd
import numpy as np
df = pd.read_csv('exp-train')
from patsy import dmatrices
#here the ~ sign is an = sign
#The C() lets our algorithm know that those variables are categorical
formula_ml = 'TripType ~ VisitNumber + C(Weekday) + Upc + ScanCount + C(DepartmentDescription)+ FinelineNumber'
#assign the variables
Y_train, X_train = dmatrices(formula_ml, data=df, return_type='dataframe')
Y_train= np.asarray(Y_train).ravel()
您可以通过更改公式来选择要用于机器学习算法的功能
纯python代码可能非常慢-这就是为什么numpy等都是用C、Fortran和Cython编写的 例如,纯python中的整数是使用12字节而不是8字节存储的。通过
append
构建整数的list()
,预计速度缓慢且成本高昂
要加快速度,请尝试
还可以使用python探查器来识别热点所在的位置。最后一条if语句应该缩进感谢回复,但我无法理解Patsy。我试着打印
Y\u train
,它给出[999,30,30,26,26]
,如果它根据VisitNumber考虑唯一样本,它应该打印[999,30,26]
。对不起,如果Patsy真的在处理这件事,但我不明白。最后,我需要一个矩阵,它的行数(唯一样本)比原始数据帧少,列数(特征)多。我只设置1是有道理的,但我该怎么做呢?零给了我一个特征不存在的信息