接着前一篇文章房屋建议租金机器学习算法思路继续分析, 这次我们着重思考怎么评估我们的算法.
方法分析
上一篇我们用随机暴力试探得到 中的值, 大约是 34, 但是这个暴力随机的方法好不好?
评估一个算法可以从几个方面考虑:
算法的结果准不准, 不管白猫黑猫, 抓到老鼠就好猫.
算法的训练 train 的速度快不快, 性能好不好, 一年只抓到一只老鼠的也不是好猫.
算法是不是可以被理解, 如果自家的猫只要一念咒语就会出现一只死老鼠, 这样的猫也太恐怖了.
第 2 点性能评估容易, 只要在 train 函数加入时间输出就可以了, 如果进一步考虑的话可以跟踪输出 cost 值的下降曲线, 看它是否能比较快的到达最终结果, 毕竟最后那些 + 0.1 又 - 0.1 来回震荡的时间没啥意义.
第 3 点可理解性也不难, 毕竟算法是我们自己写的, 绝大多数时候我们自己还是可以解释清楚猫是怎么抓老鼠的, 比如我们这个暴力靠近的方法中间没有任何魔法.
第 1 点稍微麻烦些, 怎么知道 34 这个结果是不是足够好? 很简单, 用用就知道, 我们用这个 34 来预测些未知的房屋面积, 看看是不是靠谱, 有多靠谱就好了.
性能评估
我们准备用 plotly 把 100 次循环中 cost 下降的情况绘制出来, 下面的代码执行绘图:
- import plotly.offline as py
- import plotly.graph_objs as go
- py.init_notebook_mode()
- costData=go.Scatter(
- x=[n for n in range(100)],
- y=[0 for n in range(100)],
- )
- costLayout = go.Layout(
- title='Cost 下降曲线',
- autosize=False,
- width=500,
- height=500,
- xaxis=dict(
- autorange=False,
- range=(0, 100),
- dtick=10,
- showline=True,
- mirror='ticks',
- title='Loops',
- rangemode='tozero'
- ),
- yaxis=dict(
- autorange=True,
- showline=True,
- mirror='ticks',
- title='Costs',
- rangemode='tozero'
- ),
- )
- costFig = go.FigureWidget([costData],costLayout)
- costFig
- train()
如果执行这个代码会出现一个图:
这是因为我们没有在 train 函数中更新绘图数据.
修改上面的 train 函数:
- import time
- def train():
- start = time.time()
- lastA = 1
- lastCost = 0
- learnRate = 1
- for i in range(100):
- newA = lastA + learnRate
- newCost = getCost(newA)
- if newCost> lastCost:
- learnRate = learnRate * (-1)
- lastCost = newCost
- lastA = newA
- #更新 costFig
- dataY = list(costFig.data[0]['y'])
- dataY[i] = newCost
- costFig.data[0]['y'] = dataY
- end = time.time()
- print('>耗时:{}毫秒'.format(end - start))
- return newA
运行得到:
可以从图中看到 33 次左右之后 cost 价值就不再降低, 也就是已经达到最优值 34 左右了, 整个耗时 4.34 秒, 但其中大部分时间 (30 多次之后) 纯粹是在做无意义的震荡.
没有对比就没有伤害, 初来乍到的我们目前还不好说这个算法的性能是否够好, 但是, 可以把这个作为一个参考, 在此基础上进行优化.
精准度评估
我们的模型 是否好用? 我们需要用事实来检测, 我们的模型只使用了 100 个样本进行训练, 我们可以拿另外 100 个样本让它来评估一下, 给出推荐租金, 然后我们再对比这个推荐租金和真实租金之间的差距, 可以把它作为模型的精准度.
评估函数及执行评估 代码:
- def evaluate(a):
- cost_li=[]
- for n in range(0,100):
- item=df.loc[n]
- area=float(item['area'])
- predict=a*area
- offset=float(item['money'])-predict
- cost_li.append(offset)
- return cost_li
- evalLi=evaluate(34.8)
对评估结果绘图.
- import random
- import plotly.offline as py
- import plotly.graph_objs as go
- py.init_notebook_mode()
- evalData=go.Scatter(
- x=[n for n in range(100)],
- y=[evalLi[i] for i in range(len(evalLi))],
- )
- evalLayout = go.Layout(
- title='预测评估',
- autosize=False,
- width=500,
- height=500,
- xaxis=dict(
- autorange=False,
- range=(0, 100),
- dtick=10,
- showline=True,
- mirror='ticks',
- title='Loops',
- rangemode='tozero'
- ),
- yaxis=dict(
- autorange=False,
- range=(-10000, 10000),
- showline=True,
- mirror='ticks',
- title='Offsets',
- ),
- )
- evalFig = go.FigureWidget([evalData],evalLayout)
- evalFig
- print('平均偏差:{}'.format(sum(evalLi)/len(evalLi)))
对于 100~200 之间的样本预测, 得到很大的偏差 - 512, 差距很大. 而且分布非常不均匀, 很多偏差都超过正负 1000, 就是说预测租金和实际租金相差超过 1000 元, 这个还是很糟糕的.
如果我们改为预测 0~100 个样本(就是 train 也使用的这个样本范围), 那么平均偏差只有 - 300 左右, 还是可以的.
你可以尝试调整更多参数, 不同的样本范围, 不同的 a 值进行测试. 更多的进一步修正我们后续慢慢改进.
恭祝各位除夕快乐! 预祝大家新的一年, 万事如意, 训练速度越来越快, 模型精度越来越高ヽ (゚゚) ノ!!
来源: http://www.jianshu.com/p/a7509e764f16