虽然接触机器学习已经有一段时间了,但是昨天是第一次用代码实现了线性回归的过程,一直搞到晚上一点,确实解决了我很多疑问,所以特地记录一下。但是这个是我们的机器学习作业,希望我的同学可以晚点看见这篇blog,不然我实验报告就白写了。。。。(数据集已上传,找不到的话可以私聊我)
问题:
具体要求:
- 导入数据:将鲍鱼数据集abalone读取为Pandas的DataFrame格式,读取时请添加表头,即参数names取值为上表中的列名。数据探索性分析:可包括但不限于:查看数据的信息、数据维度、特征的取值、特征的分布情况,特征之间的相关性等。
- 数据预处理:
- 查看是否有缺失值,若有,请填充缺失值;
- 对特征sex (采用pandas的get_dummies) 进行one-hot编码;
- 构造新的标签列为,替换原有的rings列
- 分离标签 y和特征X
- 将数据集划分为训练集和测试集,其中,训练集为X_train(80%),训练集标签为y_train,测试集为X_test,测试集标签y_test
代码:
import pandas as pd
import os
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score
import warnings
warnings.filterwarnings('ignore') #忽略因为numpy版本问题引发的警告
#声明全局变量
data=pd.read_csv('data.csv')
m,n=data.shape #行列数
name=["性别","壳体最长长度","直径","高度","总重量","肉重量","内脏重量","壳体重量","环数量"]
new_data_path='data_afterproc.csv' #数据预处理后的文件名
#插入表头
def insert_head():
global data,m,n,name
if data.iloc[0,0]!='性别': #还没插表头
data=pd.read_csv('data.csv',header=0,names=name)
data.to_csv('data.csv',index=False,encoding="utf_8_sig")
#数据探索性分析
def data_research():
global data,m,n,name
print('数据探索性分析:')
print('一共有{}行数据,{}个标签值,其中'.format(m,n))
info=data.iloc[:,1:] #第一个属性是离散的不需要分析
for s in name[1:]:
print('标签{}的取值范围为:{}--{}\t标准值:{}\t方差:{}\t均值:{}'.format(s,
min(data.loc[ : ,s]),
max(data.loc[ : ,s]),
info.describe()[s]['50%'],
info.describe()[s]['std'],
info.describe()[s]['mean'],
))
#数据预处理
def data_preprocess():
global data,m,n,name
if data.isnull().any().all():
data1.dropna(axis=0) #这里是考虑到数据量较大,所以若存在缺失值则直接进行删除
# data.loc['性别'].replace(['M','F','I'],[0,1,-1]) #其实这个有时候也可以,但是你不知道设成什么好,
#像这里为什么是0,1,-1而不是1,2,3呢?你说不出来吧,所以设哑变量更好
sex_dummies=pd.get_dummies(data.loc[:,'性别']) #变哑变量
data=data.drop('性别', axis=1) #删掉性别属性,换成性别的哑变量
#data2 = pd.concat([sex_dummies,data]) #这个会出现nan的情况,下面用一个土方法:
data['F'] = sex_dummies.loc[:,'F']
data['I'] = sex_dummies.loc[:,'I']
data['M'] = sex_dummies.loc[:,'M']
data.loc[:,'环数量']=data.loc[:,'环数量']+1.5
Y=data.loc[:,'环数量']
data=data.drop('环数量', axis=1) #删掉环数量,是为了把它补在最后面
data['环数量'] = Y
m,n=data.shape #这里顺便更新一下全局变量
X,Y=data.iloc[:,0:-1],data.iloc[:,-1]
#保存一下处理后的数据
if os.path.exists(new_data_path):
os.remove(new_data_path)
data.to_csv(new_data_path,index=False,encoding="utf_8_sig")
return X,Y
##划分数据集:
def loadDataSet(fileName): #这个是专门用于把一个数据集拆分为训练集和测试集的
global data,m,n,name
mid=int(m *0.8) #默认取后20%作为测试集
train_dataMat = []; train_labelMat = []
test_dataMat=[];test_labelMat = []
fr = open(fileName,encoding='utf-8') #拆出训练集
for line in fr.readlines()[1:mid:]: #跳过前面名称,从第二行开始,到分界行
lineArr = []
curLine = line.strip().split(',')
for i in range(1,n-1):
lineArr.append(float(curLine[i]))
train_dataMat.append(lineArr)
train_labelMat.append(float(curLine[-1]))
fr2 = open(fileName,encoding='utf-8') #拆出训练集
for line in fr2.readlines()[mid::]: #跳过前面的分界行,直到最后一行
lineArr = []
curLine = line.strip().split(',')
for i in range(1,n-1):
lineArr.append(float(curLine[i]))
test_dataMat.append(lineArr)
test_labelMat.append(float(curLine[-1]))
return train_dataMat,train_labelMat,test_dataMat,test_labelMat
#返回训练集样本,训练集样本标签,测试集样本,测试集样本标签
if __name__ == '__main__':
insert_head()
data_research()
X,Y=data_preprocess()
X_train,y_train,X_test,y_test=loadDataSet(new_data_path)
一些之前的疑问和运行中出现的问题:
首先就是哑变量,
在一开始我采取的方法是
# data.loc['性别'].replace(['M','F','I'],[0,1,-1])
但是这个问题很大,因为你不知道为什么这么选值,你可以选(0,1,-1),(1,2,3)但是都没有道理,可是你换成哑变量之后,就只有0和1,对回归公式中前面的系数不会造成太大的影响,如果你换成(1,2,3),很明显换成3的属性对最后的预测值造成的影响更大。
其次是合并两个dataframe类型的数据
#data2 = pd.concat([sex_dummies,data])
我是想利用concat方法将sex_dummies,data这两个数据合并,但是会出现nan值,所以我用了一个很low的方法替代,就是直接复制,具体可以见我的代码。很显然这里是因为有一个数据量较小我才可以这么做,如果数据量太大的话就不支持这种做法(等我下次有解决方法了再更新吧)
本节主要涉及的是数据处理部分,也就是pandas的基本操作,之后我们将对梳理后的数据进行线性回归分析:(下一节)