学习安排(8月14日-8月15日)
1.主要学习视频Week5&小测验
链接(http://www.xuetangx.com/courses/MITx/6_00_2x/2014_T2/about)
2.辅助内容:教材第18章
胡克定律
胡克定律指出弹性与力成正比,用公式表述就是F = -kx。换句话说,弹簧中储存的力F与弹簧被压缩(或拉伸)的距离成线性关系。(负号表示弹簧发力的方向与其位移方向相反。)它不适用于任意大的力,所有弹簧都有一个弹性极限,超过这个极限的话,胡克定律就失效了。
如果在弹簧上悬挂多个重量不断增加的物体,并测量出弹簧每次
拉伸的长度,然后绘制结果,并将结果保存在springData.txt文件中:
Distance (m) Mass (kg)
0.0865 0.1
0.1015 0.15
…
0.4416 0.9
下面第代码可以从我们保存的文件中读取数据,并绘制距离和质量的数据图。
import pylab, random
def getData(fileName):
dataFile = open(fileName, 'r')
distances = []
masses = []
discardHeader = dataFile.readline()
for line in dataFile:
d, m = line.split()
distances.append(float(d))
masses.append(float(m))
dataFile.close()
return (masses, distances)
def plotData(fileName):
xVals, yVals = getData(fileName)
xVals = pylab.array(xVals)
yVals = pylab.array(yVals)
xVals = xVals*9.81 # convert mass to force (F = mg)
pylab.plot(xVals, yVals, 'bo', label = 'Measured displacements')
pylab.title('Measured Displacement of Spring')
pylab.xlabel('Force (Newtons)')
pylab.ylabel('Distance (meters)')
plotData('springData.txt')
pylab.show()
图中的点并不在一条直线上,这和胡克定律并不相符。如果有一条直线可以表示我们的最佳预测,即表示如果没有测量误差时点应该在哪个位置,那就更好了。要达到这个目的,通常的做法是使用一条直线拟合数据。
使用线性回归进行拟合
不论我们使用何种曲线(包括直线)拟合数据,都需要某种方法确定哪条曲线才是数据的最佳拟合。这意味着我们需要定义一个目标函数,对曲线拟合数据的程度提供一个定量的评价。如果我们定义了目标函数,那么找到最优拟合就可以明确表述为一个最优化问题:找到一条曲线,使目标函数值最小(或最大)。
最常用的目标函数称为最小二乘。令observed和predicted为两个同样长度的向量,observed中是实际测量出来的点, predicted中则是拟合曲线上相应的数据点。那么,目标函数就可以定义为:
PyLab中提供了一个内置函数polyfit,它可以找出最小二乘拟合的近似解。调用以下函数:
pylab.polyfit (observedXVals, observedYVals, n)
可以找出一组n阶多项式的系数,这个多项式就是定义在observedXVals和observedYVals这两个数组中的数据点的最优最小二乘拟合。举例来说,调用以下函数:
pylab.polyfit(observedXVals, observedYVals, 1)
可以找出一条由多项式y = ax + b定义的直线,这里的a是直线的斜率, b是Y轴上的截距,函数会返回一个带有两个浮点数的数组。
ployfit使用的算法称为线性回归。fitData函数扩展了上述plotData函数,添加了一条直线来表示数据的最佳拟合。它使用polyfit找出系数a和b,然后使用这些系数为每个力生成弹簧位移的预测值。
def fitData(fileName):
xVals, yVals = getData(fileName)
xVals = pylab.array(xVals)
yVals = pylab.array(yVals)
xVals = xVals*9.81 # convert mass to force (F = mg)
pylab.plot(xVals, yVals, 'bo', label = 'Measured points')
pylab.title('Measured Displacement of Spring')
pylab.xlabel('Force (Newtons)')
pylab.ylabel('Distance (meters)')
a,b = pylab.polyfit(xVals, yVals, 1) # fit y = ax + b
# use line equation to graph predicted values
estYVals = a*xVals + b
k = 1/a
pylab.plot(xVals, estYVals, label = 'Linear fit, k = '
+ str(round(k, 5)))
pylab.legend(loc = 'best')
fitData('springData.txt')
pylab.show()
调用fitData('springData.txt')会生成下面的图形:
只有很少几个点落在最小二乘拟合的直线上,这个拟合看上去不够好。我们向fitData添加一些代码,试一下三次拟合:
#find cubic fit
fit = pylab.polyfit(forces, distances, 3)
predictedDistances = pylab.polyval(fit, forces)
pylab.plot(forces, predictedDistances, 'k:', label = 'cubic fit')
这段代码会生成下面的图形。三次拟合建立的数据模型看上去要比线性拟合好很多,但真的是这样吗?未必如此。
在技术文献中,我们经常会看到类似的图,其中既有原始数据,也有一条拟合数据的曲线。然而,作者往往会将拟合曲线当作对真实情况的描述,而将原始数据看作实验误差。这是非常危险的一种做法。
理论上x值和y值应该是线性关系,而不是三次关系。但是如果使用三次模型预测悬挂1.5千克物体时弹簧的位移,那么相应的点会在哪里?如图所示。
这时,三次模型表现得就不那么好了。在弹簧上悬挂一个非常重的物体,居然会使弹簧上升得比最初的悬挂位置还高(y值是负数),这简直是天方夜谭。这种情况就是过拟合的典型例子。当模型过于复杂时,经常会出现过拟合,例如,数据量较少而参数特别多的时候。发生过拟合时,拟合模型反映出的是数据中的噪声,而不是数据中有意义的关系。过拟合模型的预测能力通常很弱,就像这个例子中一样。