[2021]从0开始的tensorflow2.0 (一) huoji 机器学习,算法 2021-07-04 1082 次浏览 1 次点赞 开个新坑,最近打算写一些不专业的tensorflow2.0的入门。不专业是因为我对算法这块研究不是特别多,所以有些写错了请在评论区指出来 首先了下面这种方程  假设x为变量、Y就是真实值, 所谓机器学习 就是用一些算法如种群算法、遗传算法等,求出这个方程的最接近Y = 0的值,那么这个Y就自然是跟 真实的值很接近了. 这就是机器学习的**不怎么正确**但是搭边的一个理解 ## 安装 请记住 tensorflow2.0是不支持比较新的python版本的! 不要直接装新版本的python 会跑不起来的!装**Python 3.7.9**就挺合适的 **不要用CPU做机器学习! 不要用CPU做机器学习! 不要用CPU做机器学习! 效率会低到让你砸电脑** 然后去这里 https://tensorflow.google.cn/install/source?hl=zh_cn#linux 查看你要安装的tensorflow2.0的支持的cudnn和cuda **请记住 不同的显卡支持的cudnn和cuda的版本不同,先确认自己的显卡支持的版本,再挑tensorflow版本**  然后安装: ```c python3 -m pip install tensorflow=版本号 python3 -m pip install keras ``` 一路等他装完就完事了 然后自行安装cudnn和cuda,下载好对应的版本一路next就行,版本一定要对,另外C盘需要40G左右的空间 ## 第一个机器学习 我们来预测一下泰坦尼克号的生存率, 大学的时候想搞个情侣在一起结婚的几率预测,不过由于缺少真实可观的数据,失败了.这件事告诉我们,得到的数据一定要: > 量大 <-数量不大很容易过拟合 真实客观 <-否则结果肯定有问题 有理有据 <- 如果你的预测数据集给比如 "今天吃饭" 却来预测 "什么时候会死" 这样是不成立的. ### 下载、解析文件 ```c import numpy as np import pandas as pd import matplotlib.pyplot as plt import os import tensorflow as tf TRAIN_DATA_URL = "https://storage.googleapis.com/tf-datasets/titanic/train.csv" TEST_DATA_URL = "https://storage.googleapis.com/tf-datasets/titanic/eval.csv" train_file_path = tf.keras.utils.get_file("train.csv", TRAIN_DATA_URL) test_file_path = tf.keras.utils.get_file("eval.csv", TEST_DATA_URL) train_data_pre = pd.read_csv(train_file_path) test_data_pre = pd.read_csv(test_file_path) print(train_data_pre.head()) ``` 请记住,我们下载的csv文件包含了泰坦尼克号的生存率,结果如下  其中survived代表是否生存 其他的,是否有兄弟姐妹,年龄,票价,是否一个人,都是能否生存的有效指标,这些指标与现实中的逻辑对应,请再次记住,**一定是现实中的逻辑对应的逻辑才能用于机器学习,机器学习不是魔法** 从这里开始,我们就不再按照谷歌的教程来做了,我们来做点自己的**(谷歌的教程是真的...一言难尽,机翻+看不懂的代码,搞得我几天都搞不定)** ### 清洗数据 机器学习里面是不需要文字的,所以我们看看文件里面有些什么分类 ```c 'sex': ['male', 'female'], 'class' : ['First', 'Second', 'Third'], 'deck' : ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], 'embark_town' : ['Cherbourg', 'Southhampton', 'Queenstown'], 'alone' : ['y', 'n'] ``` 其中 Y为(也就是真实值): > survived 只有0和1 X为(这些均为变量): > sex可以表示为0 和 1 class可以表示为 0 1 2 deck 可以表示为0 1 2 3 4 5 6 7 embark_town 可以表示为0 1 2 alone 可以表示为 0 1 让我们清洗这些数据,不用谷歌的方法清洗,那实在是太癌症了 **请记住,谷歌的官方示例代码单词拼错了 ** Southhampton <-谷歌拼的,实际上数据里面是Southampton  让我们构造一下对应的清洗地图: ```c g_flush_map = { 'sex': { 'male': 0, 'female': 1 }, 'class': { 'First': 0, 'Second': 1, 'Third': 2, }, 'deck': { 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9, 'unknown': 10 }, 'embark_town': { 'Cherbourg': 0, 'Southampton': 1, 'Queenstown': 2, 'unknown': 3, }, 'alone': { 'y': 0, 'n': 1 } } ``` 然后就是直接清洗数据了: ```c def flush_data(pData, pKey): global g_flush_map return g_flush_map[pKey][pData] def build_train_data(pData): global g_flush_map for key in pData: if key in g_flush_map.keys(): print(key) pData[key] = pData[key].map( lambda params: flush_data(params, key)) return pData ``` 调用看看: ```c train_file_path = tf.keras.utils.get_file("train.csv", TRAIN_DATA_URL) test_file_path = tf.keras.utils.get_file("eval.csv", TEST_DATA_URL) train_data_pre = build_train_data(pd.read_csv(train_file_path)) test_data_pre = pd.read_csv(test_file_path) print(train_data_pre.head()) ``` 结果:  数据是不是明显好看的多了 ### 标准化数据 请注意票价(fare)这里,这里是各种杂七杂八的船票价格,因此我们需要让他归一化,这样方便机器学习. 直接用API函数,StandardScaler.fit_transform(不用的话你要分两步先fit取得固有属性比如方差均值再transform标准化,这个以后再细说) ```c def build_train_data(pData): global g_flush_map for key in pData: if key in g_flush_map.keys(): print(key) pData[key] = pData[key].map( lambda params: flush_data(params, key)) scaler = StandardScaler() pData['fare'] = scaler.fit_transform( pData['fare'].values.reshape(-1, 1)) return pData ``` 看看效果:  ### 构造模型 keras的好处就是,能随心所欲的搭建模型跟搭建积木一样再也不用担心算法细节.因此我们来搭建模型 ```c def build_network(): # 输入层,除去survived,我们有9个要输入进来的数据 input = tf.keras.layers.Input( shape=(9,), name='Duck') # activation为激活函数,这里使用relu激活函数,不要问为什么要用,可以自己百度relu # 第一层64个神经元 model = tf.keras.layers.Dense(64, activation='relu')(input) # 第二层32个神经元 model = tf.keras.layers.Dense(32, activation='relu')(model) # 第三层一个输出 model = tf.keras.layers.Dense(1, activation='sigmoid')(model) # 定义模型 model = tf.keras.Model(inputs=input, outputs=model) # 编译模型 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) return model ``` 记住几个点: 一般逻辑回归的损失函数用binary_crossentropy比较多,optimizer优化器一般是adam,逻辑回归用sigmoid函数作为输出比较多,因为他会输出一个0到1之间的值,这个值你可以当做是 概率 ,比如 0.7 就代表偏向存活的概率为0.7 具体原因可以看 https://zhuanlan.zhihu.com/p/89391305 看看模型结构: ```c model = build_network() model.summary() ```  让我们训练它并且预测测试数据(这个测试数据也要跟训练数据一样处理),其中epochs代表训练次数: ```c test_y = test_data_pre['survived'] test_x = test_data_pre.drop(['survived'], axis=1) network_model = build_network() network_model.summary() network_model.fit( x=train_x, y=train_y, epochs=100) predict_data = network_model.predict(test_x) test_loss, test_accuracy = network_model.evaluate(x=test_x, y=test_y) print('测试数据集loss {}, 测试数据集准确率 {}'.format(test_loss, test_accuracy)) for item in range(10): print('预测生存几率: {:.2%} 实际情况: {}'.format( predict_data[item][0], test_y[item])) ``` 结果  你可以看到,准确率只有80多,这是为什么呢? **泰坦尼克号的 源数据文件太少了,而且参数太少** 能有80%+左右就已经算比较好的结果了,如果增加模型规模或者增加训练次数反而会很容易造成过拟合的现象 源码: ```c import numpy as np import pandas as pd import matplotlib.pyplot as plt import os import tensorflow as tf from sklearn.preprocessing import StandardScaler import random TRAIN_DATA_URL = "https://storage.googleapis.com/tf-datasets/titanic/train.csv" TEST_DATA_URL = "https://storage.googleapis.com/tf-datasets/titanic/eval.csv" g_flush_map = { 'sex': { 'male': 0, 'female': 1 }, 'class': { 'First': 0, 'Second': 1, 'Third': 2, }, 'deck': { 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9, 'unknown': 10 }, 'embark_town': { 'Cherbourg': 0, 'Southampton': 1, 'Queenstown': 2, 'unknown': 3, }, 'alone': { 'y': 0, 'n': 1 } } def flush_data(pData, pKey): global g_flush_map return g_flush_map[pKey][pData] def build_train_data(pData): global g_flush_map for key in pData: if key in g_flush_map.keys(): print(key) pData[key] = pData[key].map( lambda params: flush_data(params, key)) scaler = StandardScaler() pData['fare'] = scaler.fit_transform( pData['fare'].values.reshape(-1, 1)) return pData def build_network(): # 输入层,除去survived,我们有9个要输入进来的数据 input = tf.keras.layers.Input( shape=(9,), name='Duck') # activation为激活函数,这里使用relu激活函数,不要问为什么要用,可以自己百度relu model = tf.keras.layers.Dense(128, activation='relu')(input) model = tf.keras.layers.Dense(128, activation='relu')(model) model = tf.keras.layers.Dense(64, activation='relu')(model) model = tf.keras.layers.Dense(1, activation='sigmoid')(model) # 定义模型 model = tf.keras.Model(inputs=input, outputs=model) # 编译模型 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) return model train_file_path = tf.keras.utils.get_file("train.csv", TRAIN_DATA_URL) test_file_path = tf.keras.utils.get_file("eval.csv", TEST_DATA_URL) train_data_pre = build_train_data(pd.read_csv(train_file_path)) test_data_pre = build_train_data(pd.read_csv(test_file_path)) print(train_data_pre.head()) train_y = train_data_pre['survived'] train_x = train_data_pre.drop(['survived'], axis=1) test_y = test_data_pre['survived'] test_x = test_data_pre.drop(['survived'], axis=1) network_model = build_network() network_model.summary() network_model.fit( x=train_x, y=train_y, epochs=100) predict_data = network_model.predict(test_x) test_loss, test_accuracy = network_model.evaluate(x=test_x, y=test_y) print('测试数据集loss {}, 测试数据集准确率 {}'.format(test_loss, test_accuracy)) for item in range(10): print('预测生存几率: {:.2%} 实际情况: {}'.format( predict_data[item][0], test_y[item])) ``` 本文由 huoji 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。 点赞 1
还不快抢沙发