查看更多的专业文章、课程信息、产品信息,请移步至:
“人工智能LeadAI”公众号;
官网:www.leadai.org.
作者:刘凯欣
原文链接:https://www.jianshu.com/p/5e325f593926
今天要处理的问题对于一个只学了线性回归的机器学习初学者来说还是比较棘手——通过已知的几组数据预测一组数据。用excel看了下,关系不是很明显,平方,log都不是很明显,挨着试也不是办法,所以停下来理了理思路。
思路整理
磨刀时间
- tensorflow关于回归的文档教程
- udacity的Titanic实例
砍柴时间
- python读取excel表格的数据
- 尝试一维输入预测输出
- 尝试五维输入预测输出
开始磨刀
读TensorFlow教程
关于tensor,vector,matrix…
13 # a rank 0 tensor; this is a scalar with shape []
2[1, 2, 3] # a rank 1 tensor; this is a vector with shape[3]
3[[1, 2, 3], [4, 5, 6]] # a rank 2 tensor; this is a matrix with shape [2, 3]
4[[[1, 2, 3]], [[ 7, 8, 9]]] # a rank 3 tensor with shape[2, 1, 3]
上面的代码很清晰地解释了tensor,vector,matrix,还有各种情况下的[]代表什么意思,也就是我一直以来搞混的维度。虽然都是[],关键看它是vector还是matrix还是其他的三维四维的空间描述,光一个[],只能称他为tensor,[]是rank = 1的tensor,[[]]是rank=2的tensor,[[[]]]是rank=3的tensor。
磨刀获得的备选方案
- tf.contrib.learn
tf.contrib.learn是TensorFlow的高级API,定义了很多常用模型,可以简化编码。tf.contrib.learn.LinearRegressor这个函数就实现了线性回归,那么同理它可能能够实现其他回归,查看API,发现它可以实现logistic regression, linear classification, logistic classification, and many neural network classifieds and regressions. 这就给问题的解决提供了一种很好的方案,以后可以陆续尝试。 - 前天刚学的线性回归(https://www.jianshu.com/p/f39bd94d7433)
时间充足就两个都试试,否则只试第一个就好。
开始砍柴
我用jupyter notebook写的,好处在于可以分段运行,小步编写小步测试。
Python读取Excel表格
这部分不属于问题的主线,就不纠结了,随便选个方式读进来就好。前两天做udacity的第一个项目,就用到了读取csv文件的数据,我采取的方案是把excel转成csv文件,然后读取。
- xlsx另存为csv
- 测试读取,先读取前几行
1import tensorflow as tf
2import numpy as np
3import pandas as pd
4train_data_file = '/Users/liukaixin/ProductDocuments/ShaleGasPressure/train_data.csv'
5predict_data_file = '/Users/liukaixin/ProductDocuments/ShaleGasPressure/predict_data.csv'
6full_train_data = pd.read_csv(train_data_file)
7full_predict_data = pd.read_csv(predict_data_file)
8# 显示训练数据列表中的前几项数据
9print(full_train_data.head())
10# 显示预测数据列表的前几项数据
11print(full_predict_data.head())
12# 显示训练数据的shape
13print(full_train_data.shape)
14# 显示预测数据的shape
15print(full_predict_data.shape)
16# 显示pd.read_csv取回来的数据类型
17print(type(full_train_data))
三个注意点:
1、head()函数默认返回前五行。
2、习惯了其他语言,总是关心返回值,感觉python好奇怪,看不出是什么类型,填参数时候总遇到各种问题,只好不停地打印类型……pd.read_csv取回来的是个DataFrame。
3、这个DataFrame的shape为(500,6),第一维有500个数据,第二维有6个数据,可以想成6行500列,不过还是不想成行列好,我发现就把它换成tensor的写法就挺好,有时候数据多维了脑子就刻画不好了,比如这个(500,6)换成tensor就是[[1,2,3,4,5,6],[1,2,3,4,5,6],……,[1,2,3,4,5,6]]碰上再多维的,就用tensor刻画就好。
将要预测的列作为输出,并从数据表中删除
1# 将要预测的列赋值给输出
2train_data_outcomes = train_data['your outcome key']
3# 从输入DataFrame中移除
4train_data_input = train_data.drop('your outcome key', axis = 1)
5print(train_data_input)
6print(type(train_data_outcomes))
这时打印train_data_input就会发现没有输出列了,同样的方法可以随意控制输入数据的维度。
train_data_outcomes的类型是<class ‘pandas.core.series.Series’>
训练预测和评估
使用tf.contrib.learn.LinearRegressor尝试一维输入预测输出
一维输入是指x=[1,2,3,4,5,……],即只取DataFrame的某一列,通过这一列预测输出:
1# 特征列,后面是维度
2feature_columns = [tf.contrib.layers.real_valued_column("x", dimension=1)]
3# 用LinearRegressor
4estimator = tf.contrib.learn.LinearRegressor(feature_columns=feature_columns)
5input_fn = tf.contrib.learn.io.numpy_input_fn({"x":train_data_input}, train_data_outcomes, batch_size=4, num_epochs=1000)
6# 拟合.
7estimator.fit(input_fn=input_fn, steps=1000)
8print(estimator.evaluate(input_fn=input_fn))
最后输出{‘loss’: xxxxx, ‘global_step’: xxxx}
使用tf.contrib.learn.LinearRegressor尝试五维输入预测输出
换成五维的最大问题就是input_fn的第一个参数和第二个参数(即输入x和输出y)到底是要什么类型,如果还把上面的代码copy下来,只把feature_columns的dimension换成5,把input_fn中的train_data_input换成DataFrame,就会收到下面的错误:
AttributeError: ‘DataFrame’ object has no attribute ‘dtype’
由于train_data_outcomes刚才看过了Serious,长成[1,2,3,4……]这种样子,所以我想把 DataFrame转成[[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5],……]这种样子,于是我就用了比较笨的方法:
1k = []
2for i in range(500):
3tmpx = []
4tmpx.append(train_data_input['your first dimension name'][i])
5tmpx.append(train_data_input['your second dimension name'][i])
6tmpx.append(train_data_input['your third dimension name'][i])
7tmpx.append(train_data_input['your fourth dimension name'][i])
8tmpx.append(train_data_input['your fifth dimension name'][i])
9k.append(tmpx)
10print(array_train_data_x)
打印就会发现变成了想要的形式,然后放在input_fn的第一个参数里,即{“x”: k}(名字不好,随便起的,没揭示意图),但是又报了下面错误:
AttributeError: ‘list’ object has no attribute ‘shape’
于是再改,在k外面套一层np.array(k),终于可以运行了。
1feature_columns = [tf.contrib.layers.real_valued_column("x", dimension=5)]
2estimator = tf.contrib.learn.LinearRegressor(feature_columns=feature_columns)
3input_fn = tf.contrib.learn.io.numpy_input_fn({"x": np.array(k)}, np.array(f), batch_size=4,
4 num_epochs=1000)
5estimator.fit(input_fn=input_fn, steps=1000)
6print(estimator.evaluate(input_fn=input_fn))
使用tf.contrib.learn.DNNRegressor尝试5个维度输入预测输出
1feature_columns = [tf.contrib.layers.real_valued_column("", dimension=5)]
2classifier = tf.contrib.learn.DNNRegressor(feature_columns=feature_columns,
3hidden_units=[10],
4optimizer=tf.train.RMSPropOptimizer(learning_rate=.001),
5activation_fn=tf.nn.relu)
6classifier.fit(x= train_data_input,
7 y=train_data_outcomes,
8 max_steps=1000)
9print(classifier.evaluate(x= train_data_input,y=train_data_outcomes))
这个classifier.evaluate的参数和上面两种方式不同,因为这个没有input_fn,查看api,依旧看不懂类型这回事,但是我看懂了里面的方法,如果不定义x和y,就需要input_fn,如果定义了,就可以不用input_fn,所以我尝试用x和y,果然可以。
等价代码
写完这两个五维的发现同理,LinearRegression那个五维的也可以写成不带input_fn的,把fit改成x和y,不指定feature_columns的键值x就好了,否则会报Key Error,这样就不用处理输入输出了,但是少了batch_改动后的同理代码如下:
1feature_columns = [tf.contrib.layers.real_valued_column("", dimension=5)]
2estimator = tf.contrib.learn.LinearRegressor(feature_columns=feature_columns)
3# input_fn = tf.contrib.learn.io.numpy_input_fn({"x": np.array(k)}, train_data_outcomes, batch_size=4,
4# num_epochs=3000)
5# estimator.fit(input_fn=input_fn, steps=3000)
6estimator.fit(x= train_data_input,y=train_data_outcomes,batch_size=4,steps=3000)
7print(estimator.evaluate(x=train_data_input,y=train_data_outcomes))
遇到的问题
由于对API的不熟悉和对Python的不熟悉,上述东西整整搞了两天,还留下下面两个疑问,在日后的学习里会逐渐补充,但是如果会的同学能三言两语指点一二将不胜感激。
- 精度如何评估
我不关心loss的值,我只希望它能输出一个正确率,分数或小数都可以,但是我只能用最笨的办法,把输出和真实的输出用程序比一遍,但是我似乎发现evaluate有直接输出的功能,但是不会用,希望会的同学指点下。 - 如何做预测
我找到一个预测的方法
1print(estimator.predict(x= train_data_input))
2print(type(estimator.predict(x= train_data_input)))
这个方法得到一个<type ‘generator’>,我想看看它的值有哪些,得把它转成list,是这么麻烦吗?generate类型有啥好处,为什么要返回一个这个类型的对象?