如图是一份模拟得到的数据,这份是经过整理过后的真实电商数据,某些非商业的数据经过处理替换,但不会影响后续的数据分析。
假设得到一份如上的数据,我们在做具体的分析之前,先要观察数据的总体的情况。
import pandas as pd
xlsx=pd.ExcelFile('Book1.xlsx')
df=pd.read_excel(xlsx,0,index_col=None,na_values=['NA'])
df = df.fillna(0) # 将缺失值替换成0值,看情况也可替换成其他值
print(df.head())
print(df.columns)
print(df.describe()) # 查看数据的总体情况
从数据的总体情况可以看出数据的mean(平均值)和75%都和max(最大值)相差太大,说明数据的离群点很严重。这个时候考虑分类之后再做分析。
这里给出其中一种分析的示例
先看每种分类的数据大致分布
import seaborn as sns
sns.stripplot(x="店铺", y="浏览量",data = df, jitter=True) # 按类别画图
plot.show()
其中B、D、J代表各店铺分布,因为带中文,所以显示的时候变成乱码了(英文标识不会乱码)。可以看到B店的数据相比其他店的数据总体上要大。这时候可以按店铺进行分类分析,同理其他分类情况也可以用同样的方法查看数据的分布,再选择需要分类的数据。下文以B点为分类再做一次数据描述。
df1 = df.loc[df["店铺"]=="B店"] # 筛选数据
print(df1.describe())
可以发现对比刚才mean和75%与max的差距有所减少,但是差距还是很大,证明还能继续分类。为了简便这里就只以B店的分类为基础继续下面的分析。
再次筛选数据:
summary = df1.describe() # 保存下summary,下面有用
columns = summary.columns.values[1:] # 提取除ID外有数据的列名,第0列是ID(要剔除字符串的列)
print(columns)
df2 = df1.iloc[:, df1.columns.get_indexer(columns)] # 再次筛选数据
# print(df2.head())
df2Normalized = df2 #
查看盒图,盒图可以轻松的发现数据的离群点,再考虑离群点的处理,一般根据离群点的数量和重要性考虑是否删除离群点或是单独处理。
# 将数据归一化后查看盒图,分析数据的离群情况,不归一化的话遇到量级不同的数据会很难看
for i in range(len(columns)):
mean = summary.iloc[1, i+1] # 第0列为ID跳过一列
sd = summary.iloc[2, i+1]
df2Normalized.iloc[:,i:(i+1)] = (df2.iloc[:, i:(i+1)]-mean)/sd
array = df2Normalized.values
#盒图
print(array)
boxplot(array)
show()
可以从盒图的数据分布发现大多数数据列的离群点数据都比较多,只有30列的数据没有离群点,14-16列因为存在缺失值,所以图没有画出来。
遇到离群点严重的数据需要再做处理,这里需要一点电商知识才能再做处理,但是这里讨论一般的数据分析技巧,所以不做这个提及。
我们假设在没有一点电商知识下继续往下的数据挖掘工作。我们这时候的挖掘目标是从现有的数据去估算‘成交宝贝数‘和其他列的关系。
我们首先要做的就是筛选变量,我们要得出目标变量和其他变量的方差的影响,采用的方法是前向逐步回归方法。
逐步回归就是对所有的属性,每次选取一个属性做线性拟合,根据拟合的结果计算跟目标测试集的方差,根据方差最少的属性作为需要增加的变量选入。然后根据已选入的属性再做一次逐步回归直到把所有的属性选完为止。最后根据对总体方差的减速程度筛选自己需要的变量。
实现的代码如下:
def XattrSelect(x, idxset):
'''
# :param x:目标数据
# :param idxset: 需要提取的目标列名
# :return:提取后的目标数据
'''
tempindex = [columns.index(i) for i in idxset]
# print(tempindex)
return x.iloc[:, tempindex] # 这样写会提示Too many indexers
# 切分训练集与测试集
label = df2Normalized["成交宝贝数"]
columns = list(columns) # 目标测试的列名
columns.remove("成交宝贝数")
xlist = df2Normalized.iloc[:, df2Normalized.columns.get_indexer(columns)] # 剔除目标值后剩下的数据
# print(xlist)
indices = range(len(label)) # 行数
xlistTest = xlist.iloc[[i for i in indices if i % 3 == 0]]
# print(xlistTest)
xlistTrain = xlist.iloc[[i for i in indices if i % 3 != 0]]
labelTest = label.iloc[[i for i in indices if i % 3 == 0 ]]
labelTrain = label.iloc[[i for i in indices if i % 3 != 0 ]]
indexset = set(columns) # 目标测试的所有列名
attrlist = [] # 储存通过测试的列名
oosError = [] # 储存对应列名的误差
for i in range(len(columns)):
attrset = set(attrlist)
# print(attrset)
attrtryset = indexset - attrset # 需要测试的列名
# print(attrtryset)
attrtry = [ii for ii in attrtryset] # 转换成列表
# print(attrtry)
errorList = []
for iTry in attrtry:
attrtemp = [] + attrlist
attrtemp.append(iTry)
# print(attrtemp)
xTrainTemp = XattrSelect(xlistTrain, attrtemp)
xTestTemp = XattrSelect(xlistTest, attrtemp)
yTrainTemp = labelTrain
yTestTemp = labelTest
model = linear_model.LinearRegression()
model.fit(xTrainTemp, yTrainTemp)
rmsError = np.linalg.norm((yTestTemp-model.predict(xTestTemp)),2)/sqrt(len(yTestTemp))
errorList.append(rmsError)
iBest = np.argmin(errorList)
attrlist.append(attrtry[iBest])
oosError.append(errorList[iBest])
print("每次增加变量时的误差值变化")
print(oosError)
print("\n"+ "最优变量顺序")
print(attrlist)
bestindex = np.argmin(oosError)
print(oosError[:bestindex])
print(attrlist[:bestindex])
TargetAttr = attrlist[:bestindex]
xTargetlist = XattrSelect(xlist, TargetAttr)
我们取误差最低的bestindex值,则前bestindex个值对应的列就是我们的目标拟合变量。
# 建模阶段
# 首先是简单的神经网络建模
from sklearn import neural_network
from sklearn.model_selection import train_test_split
from sklearn.cross_validation import cross_val_score # K折交叉验证模块
X_train, X_test, y_train, y_test = train_test_split(xTargetlist, label, random_state=4)
# 首先使用系统默认的建模,观察下效果
### Multilayer Perceptron,多层感知器,随机梯度下降神经网络
model = neural_network.MLPRegressor() # 使用默认参数测试性能
model.fit(X_train, y_train)
print(model.score(X_test, y_test))
scores = -cross_val_score(model, xTargetlist, label, cv=5, scoring='mean_squared_error') # 使用mse的时候,因为计算的损失函数不同,优化的目标是使其最小化
print(scores)
print(scores.mean())
调参部分
active_functions = ['identity', 'logistic', 'tanh', 'relu']
hidden_layers=[(),(5,10),(20,50),(50,100),(100,200),(200,200),(200,100)]
iters = [1000,2000,3000,4000,5000,6000,7000,8000,9000,10000]
scoresstore = []
for ever in iters:
model = neural_network.MLPRegressor(hidden_layer_sizes=(20, 50),activation="tanh", max_iter=2000) # 使用默认参数测试性能
model.fit(X_train, y_train)
print(model.score(X_test, y_test))
scores = -cross_val_score(model, xTargetlist, label, cv=5, scoring='mean_squared_error') #
print(scores)
print(scores.mean())
scoresstore.append(scores.mean())
print(iters[np.argmax(scoresstore)]) # 因为上面添加了减号所以这里的目标是使其最大化,调出最优参数
plot.plot(range(len(iters)), scoresstore)
plot.show()
通过迭代集合的变量,不断调整参数,直到得到一个最优的参数
# 建模阶段
# 首先是简单的神经网络建模
from sklearn import neural_network
from sklearn.model_selection import train_test_split
from sklearn.cross_validation import cross_val_score # K折交叉验证模块
X_train, X_test, y_train, y_test = train_test_split(xTargetlist, label, random_state=4)
### Multilayer Perceptron,多层感知器,随机梯度下降神经网络
model = neural_network.MLPRegressor(hidden_layer_sizes=(20, 50),activation="tanh", max_iter=2000) # 使用默认参数测试性能
model.fit(X_train, y_train)
print(model.score(X_test, y_test))
scores = -cross_val_score(model, xTargetlist, label, cv=5, scoring='mean_squared_error') # 使用mse的时候,因为计算的损失函数不同,优化的目标是使其最小化
print(scores)
print(scores.mean())