[机器学习][3]--口袋算法与线性回归
今天将会接着第一篇文章的PLA算法接着讲下去,将会去优化PLA算法。 首先有个问题需要说一下,一般来说,如果要某个模型的可用性,最好就是利用真实数据。但是由于我没能找到好的数据来做测试,所以我下面就用随机生成的数据来做为例子了 说一下参考文章: 首先,我们看一下PLA算法的问题: 计算量太大,上次就20组数据不到,就要计算300+次 下面我们就一步一步看看如何来优化 1.先生成我们要用的数据
downr = Table[{xr = RandomReal[5], yr = RandomReal[5 - xr] + RandomReal[.5], -1}, {200}];upr = Table[{xr = RandomReal[5], yr = RandomReal[{5 - xr, 5}], 1}, {150}];2.接着我们把图画出来
data = Join[downr, upr];temp = data[[All, {1, 2}]];p1 = ListPlot[ Table[Style[temp[[i]], Hue[.25*data[[i, 3]] + .75]], {i, 1, Length[data]}], AxesOrigin -> {0, 0}, ImageSize -> Large]现在有两种颜色的点,我们的任务就是找出一条直线,把这两条直线分开。 3.我们还是使用之前的PLA算法,迭代15000次
x = data[[All, {1, 2}]];y = data[[All, 3]];lengthx = Length[x];x = Prepend[x[[#]], 1] & /@ Table[i, {i, 1, lengthx}];DIEDAI = 15000;(*迭代次数为15000次*)Ein = 0;EinTable = Table[0, {DIEDAI }];(*跟踪准确率*)EinPocket = {0, 0, 0};(*存放最好的w*)EinPN = 0;(*最好w对应的准确率*)w = {0, 0, 0};Do[ (*i是用来在x和y中循环的*) i = Mod[index, lengthx]; If[ Sign[w.x[[i]]] != y[[i]], (*Print[{Sign[w.x[[i]]],y[[i]],index,i,w,x[[2]]}];*) w = w + y[[i]]*x[[i]]; (*每次更换w,都计算下新的w的准确率*) len = 0; Do[ If[ Sign[w.x[[j]]] != y[[j]], len = len + 1; ] , {j, 1, lengthx}]; (*----------------*) Ein = 1 - len/lengthx; (*如果准确率变高了,就把最高的放在口袋里*) If[EinPN < Ein , EinPocket = w; EinPN = Ein]; ]; EinTable[[index]] = Ein ; , {index, 1, DIEDAI}]4.画出迭代后的图和准确率变化的图 画准确率变化图
ListLinePlot[EinTable, InterpolationOrder -> 0, PlotRange -> Full, AxesLabel -> {Style["迭代次数", 25, Bold], Style["准确率", 25, Bold]}, ImageSize -> Large]画线
k1 = -w[[2]]/w[[3]];k2 = -w[[1]]/w[[3]];p2 = Plot[k1*x + k2, {x, 0, 5.3}, PlotRange -> Full];Show[p1, p2]我们可以看到最后分割的直线并不好,观察右边的准确率的图可以发现,迭代的最后一步并不是准确率最好的。 于是我们使用口袋法。什么是口袋算法呢? 口袋算法就是增加一个跟踪器,该跟踪器跟踪最好的结果,并把它记录下来。这样在最后的时候,跟踪器就保留了所有迭代中表现的做好的那次迭代。可是为什么叫做口袋算法而不是什么其它的?作者解析说:想象一下,每次都把最好的结果放到口袋里,当发现更好的结果的时候,就把更好的放到你的口袋中并丢弃口袋中原有的结果。最后当算法结束时,你只需要把你口袋里面的结果拿出来就是了。所以叫做口袋算法。 上面的代码已经是口袋算法的了。 5.我们画出使用口袋算法时的分割图
k1 = -EinPocket[[2]]/EinPocket[[3]];k2 = -EinPocket[[1]]/EinPocket[[3]];p2 = Plot[k1*x + k2, {x, 0, 5.3}];Show[p1, p2]可以看到这张图就比上面的要好很多了 但是还有个问题,就是每次都从初始w={0,0,0}开始迭代,这样比较慢,有更加好的方法吗,答案是有的。 6.先使用线性回归来确定初始迭代点
lm = LinearModelFit[data, {x1, x2}, {x1, x2}];w = lm["BestFitParameters"];k1 = -w[[2]]/w[[3]];k2 = -w[[1]]/w[[3]];p2 = Plot[k1*x + k2, {x, 0, 5.3}, PlotRange -> Full];Show[p1, p2]这里插一句:本来线性回归计算出来的函数如下: 我们用来预测的话是写成 y = -2.3+0.3*x1+0.57*x2 , 但是这里我们不这么用,上面那张图里的直线就是把{-2.3,0.3,0.57}看出w。两种颜色其实就是 -2.3+0.3x+0.57y>0(<0)的部分,所以那条直线就是用 -2.3+0.3x+0.57y = 0画出来的。 7.接着用上面的w来作为初始迭代值
x = data[[All, {1, 2}]];y = data[[All, 3]];lengthx = Length[x];x = Prepend[x[[#]], 1] & /@ Table[i, {i, 1, lengthx}];DIEDAI = 15000;(*迭代次数为15000次*)Ein = 0;EinTable = Table[0, {DIEDAI }];(*跟踪准确率*)EinPocket = {0, 0, 0};(*存放最好的w*)EinPN = 0;(*最好w对应的准确率*)lm = LinearModelFit[data, {x1, x2}, {x1, x2}];w = lm["BestFitParameters"];Do[ (*i是用来在x和y中循环的*) i = Mod[index, lengthx]; If[ Sign[w.x[[i]]] != y[[i]], (*Print[{Sign[w.x[[i]]],y[[i]],index,i,w,x[[2]]}];*) w = w + y[[i]]*x[[i]]; (*每次更换w,都计算下新的w的准确率*) len = 0; Do[ If[ Sign[w.x[[j]]] != y[[j]], len = len + 1; ] , {j, 1, lengthx}]; (*----------------*) Ein = 1 - len/lengthx; (*如果准确率变高了,就把最高的放在口袋里*) If[EinPN < Ein , EinPocket = w; EinPN = Ein]; ]; EinTable[[index]] = Ein ; , {index, 1, DIEDAI}]8. 画出迭代后的图和准确率变化的图 可以看到比之前好点(其实我是挑了一个好点的,有时候结果也并不是都是好的) 这里最后结点正好在高点上,可以看准确率的图 9.画出使用口袋法的图 到这里,我们就基本把两种颜色的点分开了。还是使用了PLA算法,不过使用了线性回归来确定其初始迭代点,使用口袋法找到其最好的值。
下面还是讲一下我自己做的一个小作品。
下面链接是自己做的一个小作品,是用来学习汉字结构的,我们将汉字的结构具体展现出来了,摆脱了以往汉字教学中的模糊概念,希望大家可以看看多提提意见。
以上,所有 2017/2/10