基于:https://www.kesci.com/mw/project/5da16a37037db3002d441810
让我们开始吧。
首先的首先,至少得学一点点numpy,我不得不承认的是,“遇到再学”这种学习方法虽然很能偷懒,但是很不利于在脑内建立索引。真的吃太多亏了。
首先,这里所有的x都是横着排布的——什么意思呢?每一行代表一个example,所有的example竖着排列,具体样例可以看ex1给的数据。y都是竖着排布的——每一列代表一个result。theta都是横着的。
然后我自己的话用的是在Windows下的vscode,装了杂七杂八一堆插件。什么intelligence,pylance的。
输出单位矩阵
第一个是输出单位矩阵,我想这个是不难的,代码如下:
import numpy
a = numpy.identity(5)
print(a)
读取数据
然后就是读取数据,并将其以散点图的形式可视化,代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
path = "作业/1/data/ex1data1.txt"
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
print(data.head())
data.plot(kind='scatter', x='Population', y='Profit', figsize=(12,8))
plt.show()
这里有几个点我觉得很需要讲一讲,首先就是这个path变量,这个斜杠形式要记住,不是“/”,而是“”。然后就是这个read_csv了,虽然我们读的是txt,但好像也可以。然后是header和names,初次接触可能会有点陌生,记得去必应就好。我个人觉得,初学者没必要听大佬们讲直接读英文啥的,可以先看中文,看csdn,简书的东西——当然看英文好,看官方文档自然最好,只是太劝退了。英语极佳者可以忽略。
结果就不说了,有兴趣的可以把header,names啊这些参数随便弄一弄,看看会发生什么。
演示Cost Function
代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def model(x, theta):
return np.dot(x,theta.T)
def cost_function(x, y, theta):
inner = np.power(model(x, theta)-y, 2)
return np.sum(inner)/(2*len(x))
path = "作业/1/data/ex1data1.txt"
data = pd.read_csv(path,names=['Population', 'Profit'])
#print(data)
x = pd.DataFrame(data.Population)
x.insert(0,"default",1)
#print(x)
y = pd.DataFrame(data.Profit)
#print(y)
theta = np.matrix(np.array([0,0]))
#print(theta.shape)
print(cost_function(x,y,theta))
我们这里使用Mean Squared Error这项公式来计算偏差/误差啥的。关注函数cost_function,这就是对原始公式:
的直接翻译,当然如果你嫌代码本身的这个太麻烦了,巧妙使用矩阵直接np.dot()也是可以的。当然,你要问为什么不用别的方法,以及这个mse的优越性,那就得学数学了,很抱歉我不会(逃
演示梯度下降
先把整个代码放出来:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def model(x, theta):
return np.dot(x, theta.T)
def cost_function(x, y, theta):
inner = np.power(model(x, theta)-y, 2)
return np.sum(inner)/(2*len(x))
def error(x, y, theta):
return model(x, theta)-y
def gradient_descent(x, y, theta, alpha, iters):
for i in range(iters):
theta = theta - alpha * (1/len(x)*np.dot(error(x, y, theta).transpose(), x)) #我讨厌矩阵操作……好难
return theta
path = "作业/1/data/ex1data1.txt"
data = pd.read_csv(path, names=['Population', 'Profit'])
#print(data)
x = pd.DataFrame(data.Population)
x.insert(0, "default", 1)
#print(x)
y = pd.DataFrame(data.Profit)
#print(y)
theta = np.matrix(np.array([0, 0]))
#print(theta.shape)
model = gradient_descent(x, y, theta, 0.01, 1500)
print([1,3.5]*model.T)
print([1,7]*model.T)
x = np.linspace(data.Population.min(),data.Population.max())
print(x)
f = model[0,0]+(model[0,1]*x)
fig, ax = plt.subplots(figsize = (12, 8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()
然后慢慢来。
其实这里很多涉及的部分就是公式翻译成代码,没啥更多的。真正的精髓是为什么是这个公式。这就要去看Coursera上面的原文了。进一步的,可以看一下西瓜书和统计学习方法啥的。
原文这里使用的技术……对不起我没看懂,所以我换个了方法,就是这个:
x = pd.DataFrame(data.Population)
x.insert(0, "default", 1)
#print(x)
y = pd.DataFrame(data.Profit)
#print(y)
当然,这是因为这里只有一个x和一个y,所以可以这么偷懒:直接拿出来之后再包装一下。不过对于我这个第一次用py的人来说,我第一次看到直接惊呆了。
另外就是插入,我在这里给0这个索引这里插入了一个1,用于计算。记得我们这里所用的是一个线性模型,latex懒得打了,就是一条线。为了方便统一,加多一个(x_0 = 1)好了。
还有就是初始化( heta),我们这里就很简单了,包装成矩阵就好。由于梯度下降的特性,直接全取0就很合理。往下走吧,就是
这个梯度下降主函数了。看向里面,就只有几行:
def gradient_descent(x, y, theta, alpha, iters):
for i in range(iters):
theta = theta - alpha * (1/len(x)*np.dot(error(x, y, theta).transpose(), x)) #我讨厌矩阵操作……好难
return theta
这个也只是一个简单的翻译罢了:
其中,这个({partial( J( heta_0, heta_1))})就是这个:
当然,还没完。公式翻译成代码本身也是颇有难度的,因此,里面有些东西是需要关注一下的。我这里还是使用的点乘,用来方便地表示这个累加操作。先横后竖,这是矩阵右乘那边的一个简单的方法,本质的话看mit网课,请(
对对对我知道还有error函数,但那玩意看一下代码不就好了(逃
不过注意一下“首先,这里所有的x都是横着排布的——什么意思呢?每一行代表一个example,所有的example竖着排列,具体样例可以看ex1给的数据。y都是竖着排布的——每一列代表一个result。theta都是横着的。”
算完之后就是放图了,我觉得没啥好说的,不会的多必应就好。顺便吐个槽,之前做Games 101的作业1解析的时候,本来想事无巨细的写,毕竟真的给某些教材那种不讲人话,硬塞概念,Fly Bitch的方法搞得很恶心,想着尽可能详细点,结果写崩了,现在也就烂尾了,唉可能就画线算法要写一写吧。所以这里点到为止,主要是懒。
这玩意应该可以应付多变量的,毕竟差不多全是矩阵操作了。
对多变量的特征归一化,同时完成多变量的梯度下降
代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def model(x, theta):
return np.dot(x, theta.T)
def cost_function(x, y, theta):
inner = np.power(model(x, theta)-y, 2)
return np.sum(inner)/(2*len(x))
def error(x, y, theta):
return model(x, theta)-y
def gradient_descent(x, y, theta, alpha, iters):
for i in range(iters):
theta = theta - alpha * (1/int(x.shape[0]))*np.dot(error(x, y, theta).transpose(), x) #我讨厌矩阵操作……好难
return theta
data = pd.read_csv("作业/1/data/ex1data2.txt",header=None,names=['Size', 'Bedrooms', 'Price'])
print(data.head())
print(data.mean())
print(" ")
print(data.std())
data = (data - data.mean())/data.std()
print(data.head())
x = pd.DataFrame([data.Size,data.Bedrooms]).T
x.insert(0,"default",1)
print(x.head())
y = pd.DataFrame([data.Price]).T
print(y.head())
theta = np.matrix(np.array([0,0,0]))
model = gradient_descent(x,y,theta,0.01,1500)
print(model)
关键就是这几行:
data = (data - data.mean())/data.std()
没了。
正规方程演示
代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def normal_equation(x,y):
temp_1 = np.linalg.pinv(x.T.dot(x))
temp_2 = x.T.dot(y)
return temp_1.dot(temp_2)
'''
data = pd.read_csv("作业/1/data/ex1data2.txt",header=None,names=['Size', 'Bedrooms', 'Price'])
print(data.head())
print(data.mean())
print(" ")
print(data.std())
data = (data - data.mean())/data.std()
print(data.head())
x = pd.DataFrame([data.Size,data.Bedrooms]).T
x.insert(0,"default",1)
print(x.head())
y = pd.DataFrame([data.Price]).T
print(y.head())
print(normal_equation(x,y))
'''
path = "作业/1/data/ex1data1.txt"
data = pd.read_csv(path, names=['Population', 'Profit'])
#print(data)
x = pd.DataFrame(data.Population)
x.insert(0, "default", 1)
#print(x)
y = pd.DataFrame(data.Profit)
#print(y)
print(normal_equation(x,y))
一样,翻译公式,网站就是这个:
https://eli.thegreenplace.net/2015/the-normal-equation-and-matrix-calculus/
解释了一下公式咋来的,以及矩阵求导咋搞。老实说我还是不会,就看了个热闹(逃