写完ex3后,发现ex2的代价函数和梯度写的好傻帽, 这次完全采用向量化的写法。
1.2 Visualizing the data
X是(5000,400)的维度,共5000组样本,每组样本有400个特征,对应输出样本Y(5000,1).
// 这里的思路就是先任取100行,将这100个
//样本的400个像素点reshape成(20,20)的array,
//方便显示。每一副图占的位置要拼好了拼成10*10图片
def display_Data(X1, num=100):
# 随机决定5000行样本被挑选100行
column_X1 = np.random.choice(X1.shape[0], num)
k = 0
j = 0
X2 = np.zeros((200, 200))
for i in column_X1:
X2[20*j:20*(j+1), 20*k:20*(k+1)] = X1[i].reshape(20, 20)
k = k + 1
if k == 10:
k = 0
j = j+1
return X2
1.3.1 Vectorizing the cost function
向量化(注意:这里的Y并不是0-9,而是将其看成多次二类分后的结果,其值只能为0或1,这里我们分了10次,用for循环看成10次二类分即可,故J和二类分的相同。)
正则化:
theta(401,1)
X*theta(5000,1)
// X要增加一组偏置维度
X = np.hstack((np.ones((X1.shape[0])).reshape(X1.shape[0], 1), X1))
// An highlighted block
def g(z):
h = 1./(1+np.exp(-z))
return h
"""加上正则化的代价函数及其偏导数"""
def lrCostFunction(X, Y, theta, lmda):
m = X.shape[0] # 5000
n = X.shape[1] # 401
# fmin输出的theta是(n,)要正确运算,需reshpe 成(n,1 )
theta = theta.reshape(n, 1)
h = g(X.dot(theta))
Y = Y.reshape(m,1)
# 代价函数
J = (-Y.T.dot(np.log(h))-(1-Y).T.dot(np.log(1-h)))/m+(theta.T.dot(theta))*lmda/2/m
# J = (-Y*np.log(h)-(1-Y)*np.log(1-h)).mean()+(theta.T.dot(theta))*lmda/2/m
# 代价函数的导数
J_d = X.T.dot(h-Y)/m
J_d[0]=J_d[0]
J_d[1:] = J_d[1:] + (lmda * theta[1:]) / m
# 由于fmin 输入的函数必得是(n,)的形式,故需要将J_dreshape成(n,)的形式
J_d = J_d.reshape(J_d.size)
return J, J_d
1.4 One-vs-all Classi cation
思路:10个手写数字识别,也就是10类分,将其看成多个二类分,构造10个二类分的分类器(第一个:是1,不是1;第二个:是2,不是2,;…)。因此我们构建分类器时采用for循环(从1到10的分类器),以第一个:是1,不是1为例,我们要挑出5000个输出样本中是1的,令他们为1,不是1的令他们为0,这样我们就得到了一个1,0的输出样本Y
然后用ex2的最优化算法,求出是1,不是1对应的参数theta。这样循环10次,得到10组theta,拼成一个(401,10)的大array。参数至此训练完毕。
// An highlighted block
var foo = def one_vs_all(X, Y, num_labels, lmda):
# 特征数
n = X.shape[1]
# 几类分就训练几组theta
all_theta = np.zeros((n, num_labels))
# Y中的值是1~10
for i in range(1, num_labels+1):
# Y中等于i的令它为1,其余为0
theta_init = np.zeros((n, 1))
y = (Y == i).astype(int)
def cost_func(t):
return lrCostFunction(X, y, t, lmda)[0]
def grad_func(t):
return lrCostFunction(X, y, t, lmda)[1]
# 使用opt.fmin_bfgs()来获得最优解
theta, cost, *unused = opt.fmin_bfgs(f=cost_func, fprime=grad_func, x0=theta_init, maxiter=400, full_output=True, disp=False)
#theta = theta.reshape(n, 1)
all_theta[:, i-1] = theta
return all_theta';
注:
1.由于fmin 输入的函数必得是(n,)的形式,故需要将J_dreshape成(n,)的形式
2 fmin输出的theta是(n,)要正确运算,需reshpe 成(n,1)
3.lrCostFunction里的theta和one_vs_all是一样的,故都用theta表示。
1.4.1 One-vs-all Prediction
我们已经得到10组分类器的all_theta(401,10),还有输入样本X(5000,401),X.dot(all_theta)可以得到对应的每个样本是1-10的概率(5000,10),在每一行中选出最大概率对应的下标,就可以得到5000组样本对应的predy(5000,1)
// An highlighted block
def predictOneVsAll(X_test, all_theta):
h = g(X_test.dot(all_theta))
y_predict = np.argmax(h, axis=1).reshape(X_test.shape[0],1)
return y_predict+1
2.1 Model representation
这里的权值已经给出来了,我们只要前向传播算法即可, 它的输出是(5000,10),也是每个类的可能性。和逻辑回归一样,预测也大同小异,不做赘述。
// An highlighted block
def ex3_nn(Theta1, Theta2, X):
O_1 = g(X.dot(Theta1.T))
# 增加一个偏置维度
O_1 = np.hstack((np.ones((O_1.shape[0])).reshape(O_1.shape[0], 1), O_1))
O_2 = g(O_1.dot(Theta2.T))
return O_2
def nn_predict(Theta1, Theta2, X):
O_2 = ex3_nn(Theta1, Theta2, X)
y_predict = np.argmax(O_2, axis=1).reshape(X.shape[0], 1)
return y_predict + 1
最后补充几个python的函数
//1
y_predict = np.argmax(O_2, axis=1)
//2
column_X1 = np.random.choice(X1.shape[0], num)
//3
data = scipy.io.loadmat('data\ex3data1.mat')
Y = data['y'] # (5000,1)
X1 = data['X'] # (5000,401)
//4
y = (Y == i).astype(int)
1.O_2的每行的最大值 对应的列标。
2. 在X1.shape[0]里随机挑num个数。
3.scipy.io.loadmat输出为字典,可用data.key(),查找对应的键值
4.对于向量Y,若Y的元素为i令他为1,其余为0
注:代码已上传到github:https://github.com/hellobigorange/my_own_machineLearning/tree/master/my_ex3