相关文章推荐
冲动的水煮肉  ·  activeperl-5.10.0.1004 ...·  1 月前    · 
骑白马的烈马  ·  .NET ...·  1 年前    · 
性感的青椒  ·  Python3 通过 pika 连接 ...·  1 年前    · 
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议 》和 《 阿里云开发者社区知识产权保护指引 》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单 进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。 def setDataCollect(retX, retY): scrapePage(retX, retY, './lego/lego8288.html', 2006, 800, 49.99)#2006年的乐高8288,部件数目800,原价49.99 scrapePage(retX, retY, './lego/lego10030.html', 2002, 3096, 269.99)#2002年的乐高10030,部件数目3096,原价269.99 scrapePage(retX, retY, './lego/lego10179.html', 2007, 5195, 499.99)#2007年的乐高10179,部件数目5195,原价499.99 scrapePage(retX, retY, './lego/lego10181.html', 2007, 3428, 199.99)#2007年的乐高10181,部件数目3428,原价199.99 scrapePage(retX, retY, './lego/lego10189.html', 2008, 5922, 299.99)#2008年的乐高10189,部件数目5922,原价299.99 scrapePage(retX, retY, './lego/lego10196.html', 2009, 3263, 249.99)#2009年的乐高10196,部件数目3263,原价249.99 from bs4 import BeautifulSoup import random def scrapePage(retX, retY, inFile, yr, numPce, origPrc): # fr = open(inFile); fw=open(outFile,'a') #a is append mode writing # soup = BeautifulSoup(fr.read()) # 打开并读取HTML文件 with open(inFile, encoding='utf-8') as f: html = f.read() soup = BeautifulSoup(html) # 根据HTML页面结构进行解析 currentRow = soup.findAll('table', r="%d" % i) while(len(currentRow)!=0): #查找标题 title = currentRow[0].findAll('a')[1].text lwrTitle = title.lower()#拷贝string的副本并转换为小写 # 查找是否有全新标签 if (lwrTitle.find('new') > -1) or (lwrTitle.find('nisb') > -1):#不存在则返回-1,否则返回当前子串所在字符串位置的索引 newFlag = 1.0 else: newFlag = 0.0 # 查找是否已经标志出售,我们只收集已出售的数据 soldUnicde = currentRow[0].findAll('td')[3].findAll('span')#是否在售 sold/unsold if len(soldUnicde)==0: print("item #%d did not sell" % i)#第几项--对应第几table else:# 解析页面获取当前价格 soldPrice = currentRow[0].findAll('td')[4] priceStr = soldPrice.text priceStr = priceStr.replace('$','') #strips out $ priceStr = priceStr.replace(',','') #strips out , if len(soldPrice)>1: priceStr = priceStr.replace('Free shipping', '') #strips out Free Shipping print("%s\t%d\t%s" % (priceStr,newFlag,title))#价格 全新否 题目 #fw.write("%d\t%d\t%d\t%f\t%s\n" % (yr,numPce,newFlag,origPrc,priceStr)) sellingPrice = float(priceStr) # 去掉不完整的套装价格 if sellingPrice > origPrc * 0.5:#大于原价的一半则留下 #输出年份--乐高部件数目--全新与否--原价--销售价格(待预测量) print("%d\t%d\t%d\t%f\t%f" % (yr, numPce, newFlag, origPrc, sellingPrice)) retX.append([yr, numPce, newFlag, origPrc])#年份--乐高部件数目--全新与否--原价(特征) retY.append(sellingPrice)#真实值 i += 1 currentRow = soup.findAll('table', r="%d" % i)

–解析页面获取当前价格

注意的是:去掉不完整的套装价格(判断依据售价大于原价的一半则留下,否则认为套装不完整)

将以上每个条目(Table):年份、乐高的部件数目、全新与否、乐高玩具的原价构成特征向量

售价作为标签

建立模型预测

数据预处理

添加常数项特征:总共5个特征

xMat = mat(xArr); yMat = mat(yArr).T xTx = xMat.T*xMat#计算xTx if linalg.det(xTx) == 0.0:#判断行列式是否为0 print("This matrix is singular, cannot do inverse") return ws = xTx.I * (xMat.T*yMat)#计算回归系数 return ws

1)采用10折交叉验证以评估岭回归参数;

2)每一折验证:随机打乱数据,其中训练集和测试集的划分 90%训练 10%测试;

3)10(10折)x30(岭回归参数),通过按照列取平均可获得每个岭回归参数的10折交叉验证平均值,找出误差最小的岭回归参数。

4)数据的还原

可参考博客的数据标准化与去标准化部分的描述:回归分析及实际案例:预测鲍鱼年龄

在岭回归中要求数据要标准化再参与计算,那么在训练完成后新的数据如何进行预测?这个新的数据怎么利用训练的数据进行标准化?

解决方法是:利用在训练数据中得出的回归参数,通过变换实现变相的在新数据预测时的标准化

新的数据一般预测过程:

数据标准化:XT=(XTest-mean(XTrain))/Var(XTrain)

预测:Ytest=XT*Ws+mean(YTrain)

将上述的公式变换:

Ytest=((XTest-mean(XTrain))/Var(XTrain))*Ws+mean(YTrain)

设UnReg=Ws/Var(XTrain)

constantTerm=-mean(XTrain)*Ws/Var(XTrain)+mean(YTrain)

则Ytest=XTest*UnReg+constantTerm(现在的新变换后的预测过程)

##交叉验证--岭回归
ridgeWs,ridgeunReg,ridgeConstantTerm=crossValidation(lgX,lgY,10)#目的是找出最佳的岭回归系数
##测试均方误差
####和标准线性回归的比较
##第一种计算思路:
ridgeW=mat(ones((1,5)))#回归系数的重新组合
ridgeW[0,0]=ridgeConstantTerm
ridgeW[0,1:5]=ridgeunReg
ridgeyHat=lgX1*ridgeW.T#岭回归预测
rssError(lgY,ridgeyHat.T.A)#误差计算
##第二种计算的思路:
xMat=mat(lgX)
yMat=mat(lgY)
ridgeyHat=xMat*ridgeunReg.T+ridgeConstantTerm#岭回归预测
rssError(yMat.A,ridgeyHat.T.A)#误差计算
    m = len(yArr)#样本点个数                           
    indexList = list(range(m))
    errorMat = zeros((numVal,30))#create error mat 30columns numVal rows
    for i in range(numVal):#交叉验证
        trainX=[]; trainY=[]
        testX = []; testY = []
        random.shuffle(indexList)#随机打乱样本索引
        #训练集和测试集的划分 90%训练  10%测试
        for j in range(m):#create training set based on first 90% of values in indexList
            if j < m*0.9: 
                trainX.append(xArr[indexList[j]])
                trainY.append(yArr[indexList[j]])
            else:
                testX.append(xArr[indexList[j]])
                testY.append(yArr[indexList[j]])
        #岭回归(岭回归次数默认)
        wMat = ridgeTest(trainX,trainY)    #30*特征数 get 30 weight vectors from ridge
        #30组回归系数
        for k in range(30):#loop over all of the ridge estimates
            matTestX = mat(testX); matTrainX=mat(trainX)
            meanTrain = mean(matTrainX,0)
            varTrain = var(matTrainX,0)
            matTestX = (matTestX-meanTrain)/varTrain #regularize test with training params
            yEst = matTestX * mat(wMat[k,:]).T + mean(trainY)#test ridge results and store
            errorMat[i,k]=rssError(yEst.T.A,array(testY))
            #print errorMat[i,k]
    #计算所有这些误差值的均值
    meanErrors = mean(errorMat,0)#errorMat为 10*30   30个岭回归参数  10次交叉验证  按照把轴向数据求平均  得到每列数据的平均值,也即是10折交叉验证的平均   calc avg performance of the different ridge weight vectors
    minMean = float(min(meanErrors))#哪个岭回归参数下的误差最小
    bestWeights = wMat[nonzero(meanErrors==minMean)]#找出误差最小的回归参数
    #can unregularize to get model
    #when we regularized we wrote Xreg = (x-meanX)/var(x)
    #we can now write in terms of x not Xreg:  x*w/var(x) - meanX/var(x) +meanY
    xMat = mat(xArr); yMat=mat(yArr).T
    meanX = mean(xMat,0); varX = var(xMat,0)
    unReg = bestWeights/varX
    print("the best model from Ridge Regression is:\n",unReg)
    #标准化后数据还原
    constantTerm=-1*sum(multiply(meanX,unReg)) + mean(yMat)
    print("with constant term: ",constantTerm)
    return bestWeights,unReg,constantTerm
def ridgeRegres(xMat,yMat,lam=0.2):
    xTx = xMat.T*xMat#2*2   n*n
    denom = xTx + eye(shape(xMat)[1])*lam#n*n
    if linalg.det(denom) == 0.0:
        print("This matrix is singular, cannot do inverse")
        return
    ws = denom.I * (xMat.T*yMat)
    return ws
函数说明:岭回归参数lambda调节
Parameters:
    xArr- 特征矩阵
    yArr- 响应值
Returns:
    wMat - 返回一组w(维数和特征数对应)系数
Author:
    heda3
Blog:
    https://blog.csdn.net/heda3
Modify:
    2020-01-10
def ridgeTest(xArr,yArr):
    xMat = mat(xArr); yMat=mat(yArr).T
    #数据标准化处理
    yMean = mean(yMat,0)
    yMat = yMat - yMean     #to eliminate X0 take mean off of Y
    #regularize X's
    xMeans = mean(xMat,0)   #calc mean then subtract it off
    xVar = var(xMat,0)      #calc variance of Xi then divide by it
    xMat = (xMat - xMeans)/xVar
    numTestPts = 30#设置lambda参数迭代次数
    wMat = zeros((numTestPts,shape(xMat)[1]))#30*2的矩阵
    for i in range(numTestPts):
        ws = ridgeRegres(xMat,yMat,exp(i-10))
        wMat[i,:]=ws.T
    return wMat