我没有找到波士顿的数据集
找到了另一个房价的数据集
另一个房价数据集
可以看出来特征是二维数组,而标签是一维数组
可以看出来特征是二维数组,而标签是一维数组
可以看出来特征是二维数组,而标签是一维数组
大致意思:
一道菜可能需要1000克水,5克盐
所以水前面的系数会小,盐前面的系数会大,我现在考虑的是线性回归,即多个特征的线性组合
为了避免这种情况
我们可以使用归一化
即将原始值限制在0到1之间
1000克水去掉5克,可能没什么影响
但是5克盐去掉5克,就不行了
所以要从自身比例出发,而不是绝对值,故而归一化
上面的式子错了
大错特错
举个例子
最小值2,最大值 3
中间值2.5
2.5/(3-2)=2.5
正确的应该是分子也要减去min
没有归一化之前这些参数都是nan
由上图可知只训练一个样本就发生了这么大的变化,是怎么做到的??
我之前以为线性回归的导数就只是系数了,所以不理解这么大 的变化
那是一元是这样,多元就不一样了
遇事要动笔,光想没用
输入数据归一化之后都是在0到1之间
标签数据是在100000到1600000之间
这就是为什么损失函数可以这么大
我是这么想的
因为假设的模型是多元线性回归
所以是y=w1x1+w2x2+…+b的形式
现在归一化之后xi都是纯小数,而w是标准差为0.1的正太分布的初始值,所以也是个不大的值,个位数
这样的话求均方误差肯定很大,都上亿了
所以我把标准数据除以了100000
问题:
训练的时候用的归一化,那测试单个样本的时候怎么用归一化
个人猜测:
如果用的是最大最小值归一化
比如图像
最大值255最小值0,这样的化还可以
如果是均值平均化
那就假设训练集和测试集是满足同一分布,即有相同的均值和方差
代码如下:
```python
import tensorflow as tf
import numpy as np
import time
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.utils import shuffle
'''
本来要来弄波士顿房价数据集,但是我找不到免费的csv格式,所以就找了另一个类似的数据集也是房价的
https://www.jianshu.com/p/928b95645757
'''
#读取数据文件
df=pd.read_csv("data/kc_train.csv")#第一行数据读不到,其他行可以
# print(df.describe())
# print(df)
#获取df的值
df=df.values
#转换为numpy的数组格式
df=np.array(df)
print(df)
print("df的形状为:",df.shape)
print(df[1,:])
'''
归一化操作,这个非常重要,没有这个结果就会报nan
'''
for i in range(2,14):
# df[:,i]=df[:,i]/(df[:,i].max()-df[:,i].min())
df[:,i]=(df[:,i]-df[:,i].min())/(df[:,i].max()-df[:,i].min())
# print(i)#输出2到13
print("----------------------------------------")
print(df[1,:])
print(df)
x_data=df[:,2:]#从第三列到最后一列都是特征
y_data=df[:,1]#第二列是房屋价格,第一列是日期,我没有要这个数据
y_data=y_data/100000
# print(x_data.shape)#(9999, 12)说明是二维数组
# print(y_data.shape)#(9999,)说明是一维数组,由于是一维数组,所以谈不上是列向量还是行向量
# print(y_data.T)#由于是一维数组,所以没有转置一说,所以跟没转置一样
# print(y_data)
# print(x_data)
x=tf.placeholder(tf.float32,shape=[None,12],name="X")
y=tf.placeholder(tf.float32,shape=[None,1],name="Y")
#定义一个命名空间,方便管理
with tf.name_scope("Model"):
w=tf.Variable(tf.random_normal([12,1],stddev=0.1),name="W")
b=tf.Variable(1.0,name="B")
def model(x,w,b):
# return tf.multiply(x,w)+b#由于是矩阵相乘,所以不能用multiply
return tf.matmul(x,w)+b
pred=model(x,w,b)
#迭代次数
train_epoch=3
#学习率
learning_rate=0.05 #学习率大了会报nan,如0.5
with tf.name_scope("Loss_Function"):
loss_function=tf.reduce_mean(tf.pow(y-pred,2))#顾名思义,求2次冥
#选择梯度下降优化器
optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function)
#声明一个会话
sess=tf.Session()
#初始化变量
init=tf.global_variables_initializer()
sess.run(init)
#执行训练
for epoch in range(train_epoch):
loss_sum=0
for xs,ys in zip(x_data,y_data):
#之所以要reshape是因为解包之后的是一维数组,而输入和输出要求二维
xs=xs.reshape(1,12)
ys=ys.reshape(1,1)
# print("w的值为:",sess.run(w))
# print("b的值为:",sess.run(b))
# 这里根据zip函数,应该用的是训练一次用一个样本,即SGD,随机梯度下降,但是好像又不是随机,因为是按顺序一个个拿,反正是一次一个样本
_,loss1=sess.run([optimizer,loss_function],feed_dict={x:xs,y:ys})
loss_sum=loss_sum+loss1
#打乱数据顺序
xs1,ys1=shuffle(x_data,y_data)#xsl和ysl本身没什么用,这里就是把xdata和ydata一致的打乱
#根据zip函数在for循环中的表现,这里是全部样本训练一遍后输出依次当前权重和偏置值
b0temp=b.eval(session=sess)
w0temp=w.eval(session=sess)
loss_average=loss_sum/len(y_data)
# plt.plot(x_data,x_data*w0temp+b0temp,\
# color="r",linewidth=3)
print("epoch",epoch+1,"loss:",loss_average,"w:",w0temp,"b",b0temp)
n=np.random.randint(9999)
print(n)
x_test=x_data[n] #这里是测试,用的训练的数据,x_data是归一化之后的数据,所以很合理。实际中如果有测试集的化,应该也得先归一化然后再输入到模型中。
x_test=x_test.reshape(1,12)
predict=sess.run(pred,feed_dict={x:x_test})
print("预测值为:",predict)
real=y_data[n]
print("真实值为:",real)
#用图形来演示拟合程度,取前100个点
num=100
xx=np.arange(1,num+1)
x_test=x_data[0:num]
x_test=x_test.reshape(-1,12)
predict=sess.run(pred,feed_dict={x:x_test})
plt.plot(xx,y_data[:num],label='target') #目标取值
plt.plot(xx,predict[:num],label='preds') #预测取值
plt.legend(loc='upper right') #线条显示位置
plt.show()
上面就是归一化前和归一化后的数据
上面就是归一化前和归一化后的数据
上面就是归一化前和归一化后的数据
预测效果不怎么样
原因出在哪?下图打印了训练集中的预测值和实际值的比较
我觉得就是模型太简单,可能模型本身就不是线性的
后面碰到再来改