python画锯齿波_爬坡,从线性回归开始,数据分析中一大波数学方法即将袭来

从这篇内容开始,我将开启一个系列,从线性回归切入数据分析的核心地带,在我的知识范围内,为各位看官打开一扇门,让大家看看Python能做些什么有趣的东西,窥探让人脱发不已的程序加数学之美,希望对大家有用。顺便也作为自己的笔记,整理自己的思路,在写文过程中继续学习,拓散思维。

闲言碎语不要讲,直接进入主题,先来看看线性回归长啥样,先来个一元的。

方程嘛,长这个样子:

b65dfe39ff5f45e8a888c5dd283ddab5.png

或者这个样子:

676e10f549312c8ccd638c60a3c65cb0.png

或者这个样子:

0561f250b5474655361a55da7d7cf4f2.png

理解一下,就是Y值,等于一个系数β(有些书上是K,或者ω),乘以一个变量X,然后加上一个常数b(或者ε,或者θ),用什么字母无所谓,用英文可以,用希腊字母就稍微高级一点,反正知道啥意思就行。

上面的第三种样子,是一元线性方程的矩阵表达,或者叫向量形式。从现在开始,就要逐步开始接受并习惯矩阵和向量,这是任何数据分析的基础,也是所有机器学习和深度学习必须掌握的。拒绝掌握这个,数据分析将步履维艰,机器学习和深度学习将寸步难行。

OK,说了这么多,但线性回归有啥用呢?来看个例子,因为没有实际数据(或不方便用实际数据),我们用自己造的数据来做例子,造数据的过程,也是十分有意思的,能把数据造得客观合理,其实也是需要一点技术的哈O(∩_∩)O。上造数据的代码了,还是以学生体育成绩为样本吧:

# 在网上抄了段生成人名的代码import pandas as pddef XM(num=100):    xing = ['赵', '钱', '孙', '李', '周', '吴', '郑', '王', '冯', '陈', '褚', '卫', '蒋', '沈', '韩', '杨', '朱', '秦', '尤', '许',            '何', '吕', '施', '张', '孔', '曹', '严', '华', '金', '魏', '陶', '姜', '戚', '谢', '邹', '喻', '柏', '水', '窦', '章',            '云', '苏', '潘', '葛', '奚', '范', '彭', '郎', '鲁', '韦', '昌', '马', '苗', '凤', '花', '方', '俞', '任', '袁', '柳',            '酆', '鲍', '史', '唐', '费', '廉', '岑', '薛', '雷', '贺', '倪', '汤', '滕', '殷', '罗', '毕', '郝', '邬', '安', '常',            '乐', '于', '时', '傅', '皮', '卞', '齐', '康', '伍', '余', '元', '卜', '顾', '孟', '平', '黄', '和', '穆', '萧', '尹',            '姚', '邵', '堪', '汪', '祁', '毛', '禹', '狄', '米', '贝', '明', '臧', '计', '伏', '成', '戴', '谈', '宋', '茅', '庞',            '熊', '纪', '舒', '屈', '项', '祝', '董', '梁']    ming = ['的', '一', '是', '了', '我', '不', '人', '在', '他', '有', '这', '个', '上', '们', '来', '到', '时', '大', '地',            '为', '子', '中', '你', '说', '生', '国', '年', '着', '就', '那', '和', '要', '她', '出', '也', '得', '里', '后', '自',            '以', '会', '家', '可', '下', '而', '过', '天', '去', '能', '对', '小', '多', '然', '于', '心', '学', '么', '之', '都',            '好', '看', '起', '发', '当', '没', '成', '只', '如', '事', '把', '还', '用', '第', '样', '道', '想', '作', '种', '开',            '美', '总', '从', '无', '情', '己', '面', '最', '女', '但', '现', '前', '些', '所', '同', '日', '手', '又', '行', '意',            '动', '方', '期', '它', '头', '经', '长', '儿', '回', '位', '分', '爱', '老', '因', '很', '给', '名', '法', '间', '斯',            '知', '世', '什', '两', '次', '使', '身', '者', '被', '高', '已', '亲', '其', '进', '此', '话', '常', '与', '活', '正',            '感', '见', '明', '问', '力', '理', '尔', '点', '文', '几', '定', '本', '公', '特', '做', '外', '孩', '相', '西', '果',            '走', '将', '月', '十', '实', '向', '声', '车', '全', '信', '重', '三', '机', '工', '物', '气', '每', '并', '别', '真',            '打', '太', '新', '比', '才', '便', '夫', '再', '书', '部', '水', '像', '眼', '等', '体', '却', '加', '电', '主', '界',            '门', '利', '海', '受', '听', '表', '德', '少', '克', '代', '员', '许', '稜', '先', '口', '由', '死', '安', '写', '性',            '马', '光', '白', '或', '住', '难', '望', '教', '命', '花', '结', '乐', '色', '更', '拉', '东', '神', '记', '处', '让',            '母', '父', '应', '直', '字', '场', '平', '报', '友', '关', '放', '至', '张', '认', '接', '告', '入', '笑', '内', '英',            '军', '候', '民', '岁', '往', '何', '度', '山', '觉', '路', '带', '万', '男', '边', '风', '解', '叫', '任', '金', '快',            '原', '吃', '妈', '变', '通', '师', '立', '象', '数', '四', '失', '满', '战', '远', '格', '士', '音', '轻', '目', '条',            '呢', '病', '始', '达', '深', '完', '今', '提', '求', '清', '王', '化', '空', '业', '思', '切', '怎', '非', '找', '片',            '罗', '钱', '紶', '吗', '语', '元', '喜', '曾', '离', '飞', '科', '言', '干', '流', '欢', '约', '各', '即', '指', '合',            '反', '题', '必', '该', '论', '交', '终', '林', '请', '医', '晚', '制', '球', '决', '窢', '传', '画', '保', '读', '运',            '及', '则', '房', '早', '院', '量', '苦', '火', '布', '品', '近', '坐', '产', '答', '星', '精', '视', '五', '连', '司',            '巴', '奇', '管', '类', '未', '朋', '且', '婚', '台', '夜', '青', '北', '队', '久', '乎', '越', '观', '落', '尽', '形',            '影', '红', '爸', '百', '令', '周', '吧', '识', '步', '希', '亚', '术', '留', '市', '半', '热', '送', '兴', '造', '谈',            '容', '极', '随', '演', '收', '首', '根', '讲', '整', '式', '取', '照', '办', '强', '石', '古', '华', '諣', '拿', '计',            '您', '装', '似', '足', '双', '妻', '尼', '转', '诉', '米', '称', '丽', '客', '南', '领', '节', '衣', '站', '黑', '刻',            '统', '断', '福', '城', '故', '历', '惊', '脸', '选', '包', '紧', '争', '另', '建', '维', '绝', '树', '系', '伤', '示',            '愿', '持', '千', '史', '谁', '准', '联', '妇', '纪', '基', '买', '志', '静', '阿', '诗', '独', '复', '痛', '消', '社',            '算', '义', '竟', '确', '酒', '需', '单', '治', '卡', '幸', '兰', '念', '举', '仅', '钟', '怕', '共', '毛', '句', '息',            '功', '官', '待', '究', '跟', '穿', '室', '易', '游', '程', '号', '居', '考', '突', '皮', '哪', '费', '倒', '价', '图',            '具', '刚', '脑', '永', '歌', '响', '商', '礼', '细', '专', '黄', '块', '脚', '味', '灵', '改', '据', '般', '破', '引',            '食', '仍', '存', '众', '注', '笔', '甚', '某', '沉', '血', '备', '习', '校', '默', '务', '土', '微', '娘', '须', '试',            '怀', '料', '调', '广', '蜖', '苏', '显', '赛', '查', '密', '议', '底', '列', '富', '梦', '错', '座', '参', '八', '除',            '跑', '亮', '假', '印', '设', '线', '温', '虽', '掉', '京', '初', '养', '香', '停', '际', '致', '阳', '纸', '李', '纳',            '验', '助', '激', '够', '严', '证', '帝', '饭', '忘', '趣', '支', '春', '集', '丈', '木', '研', '班', '普', '导', '顿',            '睡', '展', '跳', '获', '艺', '六', '波', '察', '群', '皇', '段', '急', '庭', '创', '区', '奥', '器', '谢', '弟', '店',            '否', '害', '草', '排', '背', '止', '组', '州', '朝', '封', '睛', '板', '角', '况', '曲', '馆', '育', '忙', '质', '河',            '续', '哥', '呼', '若', '推', '境', '遇', '雨', '标', '姐', '充', '围', '案', '伦', '护', '冷', '警', '贝', '著', '雪',            '索', '剧', '啊', '船', '险', '烟', '依', '斗', '值', '帮', '汉', '慢', '佛', '肯', '闻', '唱', '沙', '局', '伯', '族',            '低', '玩', '资', '屋', '击', '速', '顾', '泪', '洲', '团', '圣', '旁', '堂', '兵', '七', '露', '园', '牛', '哭', '旅',            '街', '劳', '型', '烈', '姑', '陈', '莫', '鱼', '异', '抱', '宝', '权', '鲁', '简', '态', '级', '票', '怪', '寻', '杀',            '律', '胜', '份', '汽', '右', '洋', '范', '床', '舞', '秘', '午', '登', '楼', '贵', '吸', '责', '例', '追', '较', '职',            '属', '渐', '左', '录', '丝', '牙', '党', '继', '托', '赶', '章', '智', '冲', '叶', '胡', '吉', '卖', '坚', '喝', '肉',            '遗', '救', '修', '松', '临', '藏', '担', '戏', '善', '卫', '药', '悲', '敢', '靠', '伊', '村', '戴', '词', '森', '耳',            '差', '短', '祖', '云', '规', '窗', '散', '迷', '油', '旧', '适', '乡', '架', '恩', '投', '弹', '铁', '博', '雷', '府',            '压', '超', '负', '勒', '杂', '醒', '洗', '采', '毫', '嘴', '毕', '九', '冰', '既', '状', '乱', '景', '席', '珍', '童',            '顶', '派', '素', '脱', '农', '疑', '练', '野', '按', '犯', '拍', '征', '坏', '骨', '余', '承', '置', '臓', '彩', '灯',            '巨', '琴', '免', '环', '姆', '暗', '换', '技', '翻', '束', '增', '忍', '餐', '洛', '塞', '缺', '忆', '判', '欧', '层',            '付', '阵', '玛', '批', '岛', '项', '狗', '休', '懂', '武', '革', '良', '恶', '恋', '委', '拥', '娜', '妙', '探', '呀',            '营', '退', '摇', '弄', '桌', '熟', '诺', '宣', '银', '势', '奖', '宫', '忽', '套', '康', '供', '优', '课', '鸟', '喊',            '降', '夏', '困', '刘', '罪', '亡', '鞋', '健', '模', '败', '伴', '守', '挥', '鲜', '财', '孤', '枪', '禁', '恐', '伙',            '杰', '迹', '妹', '藸', '遍', '盖', '副', '坦', '牌', '江', '顺', '秋', '萨', '菜', '划', '授', '归', '浪', '听', '凡',            '预', '奶', '雄', '升', '碃', '编', '典', '袋', '莱', '含', '盛', '济', '蒙', '棋', '端', '腿', '招', '释', '介', '烧', '误', '乾',            '坤']    name_group = []    for i in range(num):        x = np.random.randint(0, len(xing)-1)        m1 = np.random.randint(0, len(ming)-1)        m2 = np.random.randint(0, len(ming)-1)        name = ('' + xing[x] + ming[m1] + ming[m2])        item = {'姓名': name}        name_group.append(item)    return name_group# 生成100个人名name_group = XM(num=100)name_df = pd.DataFrame(name_group)# 保存为csv文件,用utf-8-sig编码比较靠谱name_df.to_csv('姓名.csv', encoding='utf-8-sig')

读取上面的人名文件,下面就开始造数据,注意造数据的方法,用到了回归方程和矩阵点乘。乘法有好多种,我们一般理解的乘法是叉乘(就是这个×),但矩阵运算里面,点乘更常用(就是这个 · ),这两种乘法是有区别的哈,具体区别,篇幅有点长,看官自行百度一下。(深刻理解点乘,能让你迅速成为合格的数据分析师)

import numpy as npimport pandas as pdname_df = pd.read_csv('姓名.csv', encoding='utf-8-sig').set_index('姓名')del name_df['Unnamed: 0']  # 读完csv,把csv遗留下来的这个字段删掉rng = np.random.RandomState(5)  # 设一个随机种子,原因也请百度# 随机生成两列数据,100米成绩和身高,都是100个数据。# 只有这两列数据是硬随机生成的,其他数据都是依靠这两列数据计算得到a100_array = rng.uniform(11, 16.5, 100)tall_array = rng.uniform(150, 185, 100)name_df['100m'] = a100_arrayname_df['tall'] = tall_array# 下面,np.dot就是点乘了,矩阵运算才是python真正的优势# 这是一个二元线性回归方程,看不看得出来?# 把name_df直接作为方程的X,把[0.75, -0.015]作为系数K,# 随机数rng.uniform(15, 18, 100)可以让Y值的图形变得更宽,而不是一条直线# [0.75, -0.015]是我手动给这个方程设的一个系数,不要问我为啥要设成这个值,我是试出来的bmi_array = np.dot(name_df, [0.75, -0.015]) + rng.uniform(15, 18, 100)# bmi数据等于体重除以身高的平方,于是用bmi和身高数据,把体重算出来weight_array = pow(tall_array / 100, 2) * bmi_arrayname_df['bmi'] = bmi_arrayname_df['weight'] = weight_array# 1000米成绩,同样试一个线性回归方程,多元的,系数也是我试出来的哈a1000_array = np.dot(name_df, [0, -0.2, 1.9, 3.5]) + rng.uniform(-10, 10, 100)name_df['1000m'] = a1000_array# 打印和describe一下,看看数据是否合理print(name_df)print(name_df.describe())# 把最大体重和最小体重的人找出来看看数据是否合理,不合理就调整系数,再运行一次print(name_df.loc[name_df['weight']==name_df['weight'].min()])print(name_df.loc[name_df['weight']==name_df['weight'].max()])# 存为csv文件name_df.to_csv('体育成绩表.csv', encoding='utf-8-sig')

数据造完了,长得类似这样:

d022157d457e3be4df7bdc176585e324.png

身高、体重、BMI值、100米跑步成绩、1000米跑步成绩,有点像实际数据吧(●'◡'●),下面开始分析一下,身高、体重、bmi和100m、1000m之间的关系。

import warningswarnings.filterwarnings("ignore")import mglearnimport pandas as pdfrom pandas.plotting import scatter_matriximport numpy as npfrom sklearn.linear_model import LinearRegressionfrom sklearn import metricsimport matplotlib.pyplot as pltimport matplotlib as mplmpl.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体mpl.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题sport_data = pd.read_csv('体育成绩表.csv', encoding='utf-8-sig').set_index('姓名')# 如果读完csv,有Unnamed: 0字段,这个字段删掉# del name_df['Unnamed: 0']factor_name = 'tall'  # 设置X值字段target_name = '100m'  # 设置Y值字段model = LinearRegression()  # 建一个线性回归模型# 给X值扩一个维度,前方高能:这里所说的维度,并不是矩阵的宽度,即并不是数据有多少列# 继续高能:这里说的维度,是向量维度,直观上是一列数外围有几层方括号,2层方括号就是2维# 这个对维度的理解,非常重要,机器学习和深度学习,需要十分关注模型中数据维度的变化,否则会报错X = np.array(sport_data[factor_name][:, np.newaxis])# 把X值和Y值拟合一下,Y值就是sport_data[target_name]model.fit(X, sport_data[target_name])print('拟合斜率:', model.coef_[0])  # 拟合斜率print('拟合截距', model.intercept_)  # 拟合截距# 输入X值,用模型预测一下Y值,实际上就是在一堆散点中间,画一条回归线ytest = model.predict(X)# 画图fig = plt.figure(figsize=(10, 6))ax1 = fig.add_subplot(111)# 原始数据散点ax1.scatter(X, sport_data[target_name], marker='.', color='K')ax1.plot(X, ytest, color='r')  # 回归线,即预测数据# 误差线,每一个原始数据和预测数据之间的误差,这个值越小,说明数据越能用回归模型来说明,预测能力也更强ax1.plot([sport_data[factor_name], sport_data[factor_name]], [sport_data[target_name], ytest], color='gray')plt.show()

身高和100m跑步成绩的关系图如下:

6cdebfbe53732791c081e49a4ce4f56b.png

散点和回归线离得很开,回归线也很平,说明身高和100m跑步成绩基本没啥关系哈。

如果要看其他字段之间的相关性,更换factor_name和target_name即可,它俩都可以设为tall,weight,bmi,100m,1000m中间的任何一个。

我们把actor_name和target_name分别设成tall和1000m的时候,情况是这样的

66434efaab1e75fb0716e5ae3733ca70.png

说明身高和1000m跑步成绩的关系很大啊,基本正相关。

而bmi和100米的情况是这样的

a108521bd09b44adaa93f091e15445af.png

嗯,bmi和100米跑步成绩的关系也很正相关,而且体现出了比较明显的橄榄型,我造的数据,水平高不高O(∩_∩)O。

模型的评估:

# 平均绝对误差(MAE)# MAE用来衡量预测值与真实值之间的平均绝对误差,MAE越小表示模型越好def MAE(y, y_pre):    return np.mean(np.abs(y - y_pre))# 均方误差(MSE)# MSE也许是回归中最普通的评价指标,MSE越小表示模型越好def MSE(y, y_pre):    return np.mean((y - y_pre) ** 2)# 均方根误差(RMSE)# RMSE是在MSE的基础之上开根号而来,RMSE越小表示模型越好def RMSE(y, y_pre):    return np.sqrt(MSE(y, y_pre))# 平均绝对百分比误差(MAPE)# MAPE和MAE类似,只是在MAE的基础上做了标准化处理,MAPE越小表示模型越好def MAPE(y, y_pre):    return np.mean(np.abs((y - y_pre) / y))# sklearn在实现线性回归时默认采用了R^2指标,R^2越大表示模型越好def R2(y, y_pre):    u = np.sum((y - y_pre) ** 2)    v = np.sum((y - np.mean(y)) ** 2)    return 1 - (u / v)

我们把bmi和100米跑步成绩的模型,用上面这些函数去评估一下性能。

mae_value = MAE(sport_data[target_name], ytest)mse_value = MSE(sport_data[target_name], ytest)rmse_value = RMSE(sport_data[target_name], ytest)mape_value = MAPE(sport_data[target_name], ytest)R2_value = R2(sport_data[target_name], ytest)print('mae_value^2:', mae_value)print('mse_value:', mse_value)print('rmse_value:', rmse_value)print('mape_value:', mape_value)print('R^2:', R2_value)

a31a51093512ebbda0c79955ab398994.png

嗯哼,R^2只有0.67哈

R^2是个什么东东呢?这里解释一下:R^2一般称为决定系数(coefficient ofdetermination),有的教材上翻译为判定系数,也称为拟合优度。决定系数反应了y的波动有多少百分比能被x的波动所描述,即表征依变数Y的变异中有多少百分比,可由控制的自变数X来解释。意义:拟合优度越大,自变量对因变量的解释程度越高,自变量引起的变动占总变动的百分比高。观察点在回归直线附近越密集。

而tall和1000米跑步的R^2也差不多是0.67左右,大家可以自己换着算一下,这两对数据,在单一对照的时候,表现是比较好的了,这个值:0.67,先记着。

单一对照,或称“单因子”,最好情况判断系数0.67,如何提高这个判断系数,让学生身体素质更好的解释100m或1000m跑步成绩呢?

下面我们来弄个多因子,也就是多元线性回归:

# 先看看多元变量之间是否存在线性相关scatter_matrix(sport_data[['tall', 'weight', 'bmi', '100m', '1000m']], figsize=(10, 6), diagonal='kde', alpha=0.8, range_padding=0.1, cmap=mglearn.cm3)plt.show()

b5369ec0352318ba97554c99b8cb109c.png

把所有因子对的情况一次性画出来,发现体重和1000m的线性关系不错哦,补一张图,weight和1000m的关系

eee6b9abacebcbe142839762e6df7d53.png

嗯,R^2也不错,有0.95,我们再记一下。

23a32447cac2dc9b7e7b97532e9503a3.png

而多因子线性回归,试试看,能否在0.95的情况下再提高一把呢?

model_multi = LinearRegression()# 把身高、体重、bmi和100m成绩作为因子,把1000m成绩作为Y值# 考察这四个因子对1000m跑步成绩的影响model_multi.fit(sport_data[['tall', 'weight', 'bmi', '100m']], sport_data['1000m'])print('斜率a为:',model_multi.coef_)print('截距b为:%.4f'%model_multi.intercept_)print('线性回归函数为:1000m = %.1f*tall + %.1f*weight + %.1f*bmi + %.1f*100m + %.1f'%(model_multi.coef_[0],model_multi.coef_[1],model_multi.coef_[2],model_multi.coef_[3],model_multi.intercept_))ytest_multi = model_multi.predict(sport_data[['tall', 'weight', 'bmi', '100m']])mae_value = MAE(sport_data['1000m'], ytest_multi)mse_value = MSE(sport_data['1000m'], ytest_multi)rmse_value = RMSE(sport_data['1000m'], ytest_multi)mape_value = MAPE(sport_data['1000m'], ytest_multi)R2_value = R2(sport_data['1000m'], ytest_multi)print('mae_value^2:', mae_value)print('mse_value:', mse_value)print('rmse_value:', rmse_value)print('mape_value:', mape_value)print('R^2:', R2_value)

9fe8f65d1489241671c56f33683c1147.png

判断系数提高到0.968了,O(∩_∩)O

但这种图,我是画不出来的,只能根据数值去脑补了。在单独因子并不能很好的说明问题的时候,有时候组合因子,是可以对模型效果做出提升的。现实世界中通常都会出现这种叠加增益情况。

这样做的意义是什么呢?

意义是,当我们掌握了一个学生的身高和体重之后,测一下他的100米跑步成绩,就基本知道他1000米能跑多快了……

当然,这个例子中的数据是假的,现实中实际数据是不是这个情况,有条件的同学可以自己去验证一下。

而且,这一套逻辑和算法,完全可以用在其他领域和场景中。

再复习一下本篇真正的核心内容:

1、矩阵运算,例如点乘,或另一种乘法,例如卷积,是python的真正优势

2、向量概念很重要,向量维度和数据维度,是两个不同的东西

打完收工!

03aa8db5c6ac884889ec5ff6ee14b770.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值