NJUPT 南京邮电大学 Python编程及人工智能应用实验报告(二)

实验二:线性回归与逻辑斯蒂分类实验 

  • 实验目的和要求
    1. 掌握线性回归的基本原理。
    2. 掌握逻辑斯蒂分类的基本原理。
    3. 学会使用Python语言实现线性回归算法。
    4. 学会使用Python语言实现逻辑斯蒂分类。
  • 实验原理及内容
  1. 使用线性回归对房屋价格(数据集:题目1数据.txt)进行预测,需要使用前350行作为训练,351-414行作为测试数据,并对测试数据输出评价指标R方和残差平方和。
    1. 用sklearn实现线性回归;
    2. 再用最小二乘或梯度下降法实现(参考书上代码)。
    3. 选用随机种子42:np.random.seed(42)

提示:先把数据复制到文本文件,保存为data.txt,在用np.loadtxt()函数进行读取,示例代码如下

import numpy as np

a = np.loadtxt("data.txt")

注意data1.xlsx中数据的最后一列是y值,其它列是属性。

数据的话是形如以下内容的格式,如需要下载,就用百度云的此链接下载1QKjs0kBSa9e_DUbivwwaLQ 提取码:jpl4

 32    84.87882    10    24.98298    121.54024    37.9
19.5    306.5947    9    24.98034    121.53951    42.2
13.3    561.9845    5    24.98746    121.54391    47.3
13.3    561.9845    5    24.98746    121.54391    54.8
5    390.5684    5    24.97937    121.54245    43.1
7.1    2175.03    3    24.96305    121.51254    32.1
34.5    623.4731    7    24.97933    121.53642    40.3
20.3    287.6025    6    24.98042    121.54228    46.7
31.7    5512.038    1    24.95095    121.48458    18.8

   可以看到给出的数据都是用制表符tab键隔开,且数据给的很规矩,用loadtxt不会报错,所以照着书抄一遍代码即可完成。

第一题是非常简单的线性回归,首先将数据读入,并把训练数据和测试数据划分好,可以看到一共414行数据

 

data = np.loadtxt("E:/progress/B21030826/python/data.txt")
print(data.shape)

# 划分训练集和测试集
x_train = data[:350, :-1]  # 0~349,取除了最后一位
y_train = data[:350, -1]  # 0~349,取最后一位
x_test = data[350:415, :-1]  # 350~414
y_test = data[350:415, -1]  # 取最后一位

 然后训练模型

# 使用sklearn实现线性回归
model = LinearRegression()
model.fit(x_train, y_train)

最终计算残差平方和和r方完成题目要求

# 计算残差 因为._residues版因版本问题可能无法访问
# 所以先根据模型进行预测
y_pred = model.predict(x_train)
residuals = y_train - y_pred

# 再计算R方和残差平方和
r2 = model.score(x_test, y_test)
rss = np.sum(np.square(residuals))

print("使用sklearn实现线性回归:")
print("R方是:{:.4f}".format(r2))
print("残差平方和是:{:.4f}".format(rss))

接下来使用最小二乘法完成,本质一样不多赘述,直接给出第一题的全部完整代码。

import numpy as np
from sklearn.linear_model import LinearRegression

# 读取数据
data = np.loadtxt("E:/progress/B21030826/python/data.txt")
print(data.shape)

# 划分训练集和测试集
x_train = data[:350, :-1]  # 0~349,取除了最后一位
y_train = data[:350, -1]  # 0~349,取最后一位
x_test = data[350:415, :-1]  # 350~414
y_test = data[350:415, -1]  # 取最后一位
print(x_train.shape)
print(x_test.shape)
# 使用sklearn实现线性回归
model = LinearRegression()
model.fit(x_train, y_train)
# 计算残差 因为._residues版因版本问题可能无法访问
# 所以先根据模型进行预测
y_pred = model.predict(x_train)
residuals = y_train - y_pred

# 再计算R方和残差平方和
r2 = model.score(x_test, y_test)
rss = np.sum(np.square(residuals))

print("使用sklearn实现线性回归:")
print("R方是:{:.4f}".format(r2))
print("残差平方和是:{:.4f}".format(rss))


def linreg_martix(x, y):
    X_X_T = np.matmul(x, x.T)
    X_X_T_1 = np.linalg.inv(X_X_T)
    X_X_T_1_X = np.matmul(X_X_T_1, x)
    x = np.matmul(X_X_T_1_X, y.T)
    return x


# 使用最小二乘法实现线性回归
# 对x进行扩展,加入全1的行
def make_ext(x):
    ones = np.ones(1)[:, np.newaxis]
    new_x = np.insert(x, 0, ones, axis=0)
    return new_x


# 添加偏置项1
x = make_ext(x_train.T)
y = y_train.T
w = linreg_martix(x, y)
print("w =", w)

y_train_predict = w.dot(x)
y_test_predict = w.dot(make_ext(x_test.T))

ssRTrain = sum((y_train - y_train_predict) ** 2)
ssRTest = sum((y_test - y_test_predict) ** 2)
SST = sum((y_test - np.mean(y_test)) ** 2)
rs = 1 - ssRTest / SST

print("使用最小二乘法法实现线性回归:")
print("R方是:{:.4f}".format(rs))
print("残差平方和是:{:.4f}".format(ssRTrain))

运行一下,结果如下: 


        应该没什么大错 

2、编写代码,使用Logistic Regression对训练数据(题目2训练数据.txt)进行模型训练,并针对测试数据(题目2测试数据.txt)输出二分类结果,结果用0-1之间的概率表示,用空格进行分割,分别计算在训练集和验证集(训练数据后20%)的AUC值。

  • 数据集说明
            该数据集需要通过特征数据分析,来预测二分类的结果。训练数据集中的二分类结果已经给出,为最后一列。
  • 数据集信息
            本数据集用于估计信用卡的违约概率。其中训练数据包括27997个样本,测试数据包括2001个样本。需要根据训练数据,建立Logistic Regression模型,对测试数据集中的数据预测结果。
            结果文件为一个result.txt文件,其中包含2000个0-1之间的实数值,保留两位小数,用逗号分割,例如:
            0.1, 0.2, 0.05, 1
  • 数据属性

    本数据集供包括23个特征,具体说明如下:

    - 第1列: 信用卡的额度

    - 第2列: 性别 (1 = male; 2 = female).

    - 第3列: 教育 (1 = graduate school; 2 = university; 3 = high school; 4 = others).

    - 第4列: 婚姻状态 (1 = married; 2 = single; 3 = others).

    - 第5列: 年龄.

    -  第6 - 11: 过去几个月的还款状态(4月到9月),-1,-2代表按时还款,其他代表延迟还款的月份数

    -  第12 - 17: 过去几个月的账单记录

    -  18 – 23 : 过去几个月的支付记录

    -  最后一列为类别y值,取值为0或1

    要求:

    (1)使用Sklearn实现

    (2)自定义编码使用梯度下降法实现(选做)

数据例子如下,同样百度云链接 链接:170khaDoX5jwchBOhYxsUKw 提取码:d46q

20000    2    2    1    24    2    2    -1    -1    -2    -2    3913    3102    689    0    0    0    0    689    0    0    0    0    1
120000    2    2    2    26    -1    2    0    0    0    2    2682    1725    2682    3272    3455    3261    0    1000    1000    1000    0    2000    1
90000    2    2    2    34    0    0    0    0    0    0    29239    14027    13559    14331    14948    15549    1518    1500    1000    1000    1000    5000    0
50000    2    2    1    37    0    0    0    0    0    0    46990    48233    49291    28314    28959    29547    2000    2019    1200    1100    1069    1000    0
50000    1    2    1    57    -1    0    -1    0    0    0    8617    5670    35835    20940    19146    19131    2000    36681    10000    9000    689    679    0
50000    1    1    2    37    0    0    0    0    0    0    64400    57069    57608    19394    19619    20024    2500    1815    657    1000    1000    800    0

第二题看起来很长啊,但还是非常简单的,照着书上写一遍便是了,首先根据题目要求划分训练集和验证集,可以看到数据还是很标准的制表符隔开,读取也没难度,直接给出代码。

# 读取数据
train_data = np.loadtxt('E:/progress/B21030826/python/题目2训练数据.txt')
test_data = np.loadtxt('E:/progress/B21030826/python/题目2测试数据.txt')
print(train_data.shape)
print(test_data.shape)

# 取出特征和标签
X_train = train_data[:, :-1]
y_train = train_data[:, -1]
X_test = test_data

# 划分训练集和验证集
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2)

 训练模型

# 训练模型
model = LogisticRegression()
model.fit(X_train, y_train)

计算auc值并输出

# 在训练集和验证集上计算AUC
train_auc = roc_auc_score(y_train, model.predict_proba(X_train)[:, 1])
val_auc = roc_auc_score(y_val, model.predict_proba(X_val)[:, 1])
print('Train AUC:', train_auc)
print('Val AUC:', val_auc)

 然后是预测并输出

# 在测试集上进行预测
y_pred = model.predict_proba(X_test)[:, 1]

# 输出结果
with open('E:/progress/B21030826/python/result.txt', 'w') as f:
    f.write(','.join([f'{i:.2f}' for i in y_pred]))

运行一下结果输出: 

概率输出没问题!万事大吉…………吗?

     编程完后发现到处是坑,这里小插一句,此时你可以使用y_pred=model.predict(X_test)

来获取模型在测试集上的预测结果。这种方法用于在测试集上进行分类预测,返回每个样本的预测标签。对于二分类问题,返回的结果是一个包含预测标签的一维数组。

      与model.predict_proba(X_test)[:, 1]不同的是,model.predict(X_test)直接返回预测的类别而不是概率值。该方法基于分类阈值来判断样本属于哪个类别,通常是根据0.5阈值进行判断。该代码具体为什么这么写自己搜。

      但仔细观察数据可以发现他们都小于0.5,这是什么情况?!

      我认为这是因为给出的数据中存在类别特征,就是形如1,2,3这种他需要进行独热编码处理,而其他过大的数也需要进行归一化,还有欠钱的月份如-1,-2,也可以直接合并成0再进行处理,但此时并没有学到独热编码的概念,这是第七章的内容,所以就先给出只进行归一化处理的代码

ok,既然问题找到接下来就让我进行一下数据处理吧 ,首先:

  1. 对于连续型特征:

    • 第一列,第五列和第12到23列进行归一化处理。
  2. 对于离散型特征:

    • 将-1和-2替换为0,表示按时还款。对于其他延迟还款的月份数,保留原始值。
    • 使用独热编码将第二列到第四列和第六到第十一列的数据全部处理
    • 同时因为第2到第4列分别属于不同的类型特征,而第6到11列才是另一种类型特征,理论上来说要分别进行独热编码不能混淆
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, OneHotEncoder
# 读取数据
train_data = np.loadtxt('E:/progress/B21030826/python/题目2训练数据.txt')
test_data = np.loadtxt('E:/progress/B21030826/python/题目2测试数据.txt')
print(train_data.shape)
print(test_data.shape)

# 数据处理
# 对连续型特征进行归一化处理(1,5,12-23)
continuous_features = [0, 4, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
scaler = MinMaxScaler()
train_data[:, continuous_features] = scaler.fit_transform(train_data[:, continuous_features])
test_data[:, continuous_features] = scaler.fit_transform(test_data[:, continuous_features])

# 替换-1和-2为0,表示按时还款
train_data[:, 7:23][train_data[:, 7:23] < 0] = 0
test_data[:, 7:23][test_data[:, 7:23] < 0] = 0
print(train_data.shape)
print(test_data.shape)
# 对离散型特征进行独热编码处理(2,3,4,6-11)

# 取出特征和标签
X_train = train_data[:, :-1]
y_train = train_data[:, -1]
X_test = test_data

# 划分训练集和验证集
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2)


# 训练模型
model = LogisticRegression()
model.fit(X_train, y_train)

# 在训练集和验证集上计算AUC
train_auc = roc_auc_score(y_train, model.predict_proba(X_train)[:, 1])
val_auc = roc_auc_score(y_val, model.predict_proba(X_val)[:, 1])
print('Train AUC:', train_auc)
print('Val AUC:', val_auc)

# 在测试集上进行预测
y_pred = model.predict_proba(X_test)[:, 1]

# 输出结果
with open('E:/progress/B21030826/python/result.txt', 'w') as f:
    f.write(','.join([f'{i:.2f}' for i in y_pred]))

输出结果: 

 肉眼可见的出现了0.5以上的数据,那么就先到这里吧。 

因为是4种类型特征,理论上是要分别进行四次独热编码的,同时因为编码后维度不同会出现一些问题,老是报错,所以就给出个伪代码吧,如果有兴趣的话自己试着改一改,编一编,想看人要是多的话我再改好发出来。

# 不同的类型特征要分别进行处理,不能混淆。
discrete_features = [1, 2, 3, 5, 6, 7, 8, 9, 10]
encoder = OneHotEncoder(sparse=False)
encoded_data = encoder.fit_transform(train_data[:, discrete_features])
train_data[:, discrete_features] = encoded_data

第二问选做一样是抄书上后简单的数据处理就可以了,都是选做了,你不会还要看代码是啥吧,懒得敲可以扫一下书上的二维码下载书上的代码,好了,剩下的就自己做吧 ,帮到你的话还不速速说声谢谢学长!

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值