机器学习笔记2
学习率算法:
Ada方法的核心原理
随机梯度下降法:
Feature Scaling
梯度下降法的内在原理(利用泰勒法则):
梯度下降法的限制:
HW1代码(无pytorch版):
(转https://blog.csdn.net/qq_39896020/article/details/120620126)
month_data = {} #建立了month_data字典,将每个月的数据分别储存
for month in range(12): #12个月
sample = np.empty([18,480]) #有18个数据指标,一天24h,一个月的数据有前20天的,所以20*24=480
for day in range(20): #20天
#切片赋值,举个例子,month=0,day=1时,sample[:,24:48] = raw_data[18:36,:],就是把raw_data的18——36行移到sample的24——24列,及将2014.01.02的数据移到2014.01.01的过程。
sample[:,day*24:(day+1)*24] = raw_data[18*(20*month + day):18*(20*month + day +1),:]
month_data[month] = sample #赋值存储,键为月份,值为18*480的数据表
x = np.empty([12*471,18*9],dtype=float)#初始化训练data
y = np.empty([12*471,1],dtype=float)#初始化label
for month in range(12):
for day in range(20):
for hour in range(24):
if hour > 14 and day == 19:
continue
x[month*471 + day*24 + hour,:] = month_data[month][:,day*24 + hour : day*24 + hour + 9].reshape(1,-1)
y[month*471 + day*24 +hour,0] = month_data[month][9,day*24 + hour + 9]
mean_x = np.mean(x,axis = 0) #求x均值,列
std_x = np.std(x,axis = 0) #求标准差,列
for i in range(len(x)):
for j in range(len(x[0])):
if std_x[j] != 0:
x[i][j] = (x[i][j]-mean_x[j])/std_x[j] #减均值后除标准差
# 将训练数据拆成训练数据:验证数据=8:2,这样用来验证
import math
x_train_set = x[: math.floor(len(x) * 0.8), :]
y_train_set = y[: math.floor(len(y) * 0.8), :]
x_validation = x[math.floor(len(x) * 0.8):, :]
y_validation = y[math.floor(len(y) * 0.8):, :]
dim = 18 * 9 + 1 #参数:18*9个权重 + 1个偏置bias
w = np.zeros([dim, 1]) #参数列向量初始化为0
#x新增一列用来与偏置bias相乘,将模型y=wx+b转化成y=[b,w]转置·[1,x]
x = np.concatenate((np.ones([12 * 471, 1]), x), axis=1).astype(float)
# np.ones来生成12*471行1列的全1数组,np.concatenate,axis=1
#表示按列将两个数组拼接起来,即在x最前面新加一列内容,
#之前x是12*471行18*9列的数组,新加一列之后变为12*471行18*9+1列的数组
learning_rate = 100 # 学习率
iter_time = 10000 # 迭代次数
adagrad = np.zeros([dim, 1])
# 生成dim行即163行1列的数组,用来使用adagrad算法更新学习率
eps = 0.0000000001
# 因为新的学习率是learning_rate/sqrt(sum_of_pre_grads**2),
#而adagrad=sum_of_grads**2,所以处在分母上而迭代时adagrad可能为0,
#所以加上一个极小数,使其不除0
for t in range(iter_time):
loss = np.sqrt(np.sum(np.power(np.dot(x, w) - y,
2)) / 471 / 12)
# rmse loss函数是从0-n的(X*W-Y)**2之和/(471*12)再开根号,
#即使用均方根误差(root mean square error),
#具体可百度其公式,/471/12即/N(次数)
if (t % 100 == 0): # 每一百次迭代就输出其损失
print(str(t) + ":" + str(loss))
gradient = 2 * np.dot(x.transpose(), np.dot(x,w) - y)
# dim*1 x.transpose即x的转置,后面是X*W-Y,即2*(x的转置*(X*W-Y))是梯度,
#具体可由h(x)求偏微分获得.最后生成1行18*9+1列的数组。转置后的X,其每一行是一个参数,
#与h(x)-y的值相乘之后是参数W0的修正值,
#同理可得W0-Wn的修正值保存到1行18*9+1列的数组中,即gradient
adagrad += gradient ** 2
# adagrad用于保存前面使用到的所有gradient的平方,进而在更新时用于调整学习率
w = w - learning_rate * gradient / np.sqrt(adagrad + eps) # 更新权重
np.save('weight.npy', w) # 将参数保存下来
w = np.load('weight.npy')
# 使用x_validation和y_validation来计算模型的准确率,因为X已经normalize了,
#所以不需要再来一遍,只需在x_validation上添加新的一列作为bias的乘数即可
x_validation = np.concatenate((np.ones([1131, 1]), x_validation),axis=1).astype(float)
ans_y = np.dot(x_validation, w)
loss = np.sqrt(np.sum(np.power(ans_y - y_validation, 2)) / 1131)
print(loss)
testdata = pd.read_csv('test.csv', header=None, encoding='big5')
test_data = testdata.iloc[:, 2:].copy() # 取csv文件中的全行数即第3列到结束的列数所包含的数据
test_data[test_data == 'NR'] = 0 # 将testdata中的NR替换为0
test_data = test_data.to_numpy() # 将其转换为数组
test_x = np.empty([240, 18 * 9], dtype=float) # 创建一个240行18*9列的空数列用于保存textdata的输入
for i in range(240): # 共240个测试输入数据
test_x[i, :] = test_data[18 * i: 18 * (i + 1), :].reshape(1, -1)
# 下面是Normalize,且必须跟training data是同一种方法进行Normalize
for i in range(len(test_x)):
for j in range(len(test_x[0])):
if std_x[j] != 0:
test_x[i][j] = (test_x[i][j] - mean_x[j]) / std_x[j]
test_x = np.concatenate((np.ones([240, 1]), test_x), axis=1).astype(float)
# 在test_x前面拼接一列全1数组,构成240行,163列数据
# 进行预测
w = np.load('weight.npy')
ans_y = np.dot(test_x, w) # test data的预测值ans_y=test_x与W的积
# 将预测结果填入文件当中
import csv
with open('submit.csv', mode='w', newline='') as submit_file:
csv_writer = csv.writer(submit_file)
header = ['id', 'value']
print(header)
csv_writer.writerow(header)
for i in range(240):
row = ['id_' + str(i), ans_y[i][0]]
csv_writer.writerow(row)
print(row)