linearregression_机器学习-TensorFlow建模过程 Linear Regression线性拟合应用
TensorFlow是咱們機(jī)器學(xué)習(xí)領(lǐng)域非常常用的一個(gè)組件,它在數(shù)據(jù)處理,模型建立,模型驗(yàn)證等等關(guān)于機(jī)器學(xué)習(xí)方面的領(lǐng)域都有很好的表現(xiàn),前面的一節(jié)我已經(jīng)簡(jiǎn)單介紹了一下TensorFlow里面基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)即:Tensor和Dataset; 這里咱們開始介紹TensorFlow的建模過(guò)程以及驗(yàn)證模型的一些簡(jiǎn)單方法。其實(shí)無(wú)論是sklearn還是TensorFlow,他們的模型建立過(guò)程都是相似的,都是經(jīng)歷columns類型聲明,模型定義,數(shù)據(jù)訓(xùn)練,validation等等幾個(gè)步驟。前面的幾節(jié)內(nèi)容我已經(jīng)簡(jiǎn)單的介紹了如何用sklearn建立tree_based模型,這里我主要是想演示TensorFlow的應(yīng)用,所以我就用linear regressor來(lái)當(dāng)做例子來(lái)演示TensorFlow是如何從數(shù)據(jù)加載一直到數(shù)據(jù)驗(yàn)證的階段。至于線性擬合的實(shí)現(xiàn)的具體細(xì)節(jié),我在下一節(jié)的內(nèi)容會(huì)從數(shù)學(xué)的角度具體解釋的。本節(jié)內(nèi)容所使用的數(shù)據(jù)都是來(lái)自于網(wǎng)絡(luò)中,大家可以忽略具體的數(shù)據(jù)的意思,主要的了解TensorFlow的應(yīng)用過(guò)程,不必過(guò)于糾結(jié)于模型的細(xì)節(jié)部分,模型的細(xì)節(jié)我會(huì)在隨后的章節(jié)解釋。好了,那么咱們現(xiàn)在開始吧
第一步:數(shù)據(jù)準(zhǔn)備
顧名思義,就是咱們準(zhǔn)備數(shù)據(jù)的過(guò)程,這里包括有missing value handling, categorical data encoding,data split, data permutation等等內(nèi)容,這一步咱們要將咱們將來(lái)模型訓(xùn)練所用到的數(shù)據(jù)都能準(zhǔn)備好。這個(gè)準(zhǔn)備過(guò)程無(wú)非也就是上面的這些步驟,咱們可以看下面的代碼演示
cali_housing_dataset_original = pd.read_csv("https://download.mlcc.google.com/mledu-datasets/california_housing_train.csv")cali_housing_dataset_original["median_house_value"] /= 1000.0#create a random generatorgenerator = np.random.Generator(np.random.PCG64())#permutate the data framecali_housing_dataset_permutation = cali_housing_dataset_original.reindex( generator.permutation(cali_housing_dataset_original.index) )cali_housing_dataset_permutation.describe()#select the features that we will use in the model trainning processmy_feature = cali_housing_dataset_permutation[["total_rooms"]]#select the targets of the datasettargets = cali_housing_dataset_permutation[["median_house_value"]]這里我就不演示那些feature engineering的過(guò)程,那些內(nèi)容太多,大家可以看我之前的博客,這里主要是想向大家演示一下permutation的過(guò)程。因?yàn)樽钚碌膎umpy對(duì)于randomize的過(guò)程已經(jīng)有更新了,不再使用的那些老的API了,numpy中最新的randomize的過(guò)程是通過(guò)創(chuàng)建2個(gè)generator來(lái)實(shí)現(xiàn)隨機(jī)過(guò)程和隨機(jī)數(shù)的生成了,這兩個(gè)generator一個(gè)個(gè)是bit generator, 就如咱們上面代碼中的PCG64(), 它能產(chǎn)生一個(gè)隨機(jī)的bit stream, 根據(jù)numpy的官方文檔,雖然有很多種bit generator,但是PCG64是最穩(wěn)定的一種;另外一個(gè)就是Generator, 它是通過(guò)np.random.Generator()函數(shù)來(lái)實(shí)例化一個(gè)對(duì)象的,它能將bit generator產(chǎn)生的bit stream轉(zhuǎn)化成數(shù)字。這里的數(shù)據(jù)咱們就選擇一個(gè)最最簡(jiǎn)單的linear regression的方式,那就是只選擇一個(gè)feature,那就是total_rooms; 咱們的target是median_house_value。
第二步:定義feature 類型 和 optimizer
既然咱們的數(shù)據(jù)都準(zhǔn)備好了,那么之后那么得定義一下咱們數(shù)據(jù)的類型(每一個(gè)column的類型都得定義),將來(lái)在咱們定義模型的時(shí)候咱們也得將columns的信息傳遞給咱們的模型對(duì)象;以及用什么optimizer將來(lái)來(lái)訓(xùn)練咱們的模型,這個(gè)optimizer將來(lái)也得傳遞給咱們的模型對(duì)象。 具體optimizer是什么我下面會(huì)慢慢講的。為了方便演示,還是先上代碼給大家看
#indicates what is the data type of the feature to tensorflowfeature_columns = [tf.feature_column.numeric_column("total_rooms")]#using stochastic gradient descent as the optimizer for our model#to ensure the magtitute of gradient do not become too large, we apply clipping_norm to our optimizermy_optimizer = tf.optimizers.SGD(learning_rate = 0.0000001, clipnorm=5.0)從上面的代碼可以看出,第一句是聲明咱們feature_columns里面只有一個(gè)numeric_column,記住每一個(gè)column都有一個(gè)feature_column對(duì)象,這里因?yàn)樵蹅冎贿x取了一個(gè)feature是total_rooms,所以咱們這里就一個(gè)tf.feature_column對(duì)象。這里的第二行代碼是咱們的重點(diǎn),也是以后優(yōu)化模型中經(jīng)常要調(diào)整的部分,這里咱們可以看出,這里的optimizer是一個(gè)SGD, SGD是stochastic gradient descent的縮寫,就是每一次計(jì)算咱們的gradient descent的時(shí)候,咱們只選取一組數(shù)據(jù)進(jìn)行計(jì)算,如果每一次計(jì)算gradient descent的時(shí)候咱們都用整個(gè)數(shù)據(jù)進(jìn)行計(jì)算,那么咱們的計(jì)算機(jī)是負(fù)擔(dān)不起的,消耗的存儲(chǔ)空間和計(jì)算能力都太大了,因?yàn)樵趯?shí)際中咱們的數(shù)據(jù)集的數(shù)量經(jīng)常都是以萬(wàn)為單位的。具體計(jì)算gradient descent的過(guò)程我會(huì)在下一節(jié)中講述模型訓(xùn)練過(guò)程中演示的。咱們可以看出來(lái),SGD中還有兩個(gè)參數(shù),分別是learning_rate和clipnorm, 咱們知道,當(dāng)我們?cè)谟?xùn)練我們的模型的時(shí)候,我們需要逐步的訓(xùn)練很多次,知道咱們的gradient descent趨于0是才停止,咱們的每一步的大小都要合理,如果learning_rate太小,咱們訓(xùn)練的步數(shù)就會(huì)太多,影響咱們的效率;如果learning_rate太大,則可能導(dǎo)致咱們訓(xùn)練模型的過(guò)程不能converge,就是永遠(yuǎn)找不到那個(gè)最小值,從而導(dǎo)致訓(xùn)練的模型失敗;為了防止咱們?cè)蹅兊膅radient太大,我們這里不單單用learning_rate來(lái)限制,咱們還加了一個(gè)clipnorm來(lái)限制咱們的gradient magtitute大小,防止咱們fail to converge, 這相當(dāng)于一個(gè)雙重保險(xiǎn)。
第三步:定義一個(gè)模型model
將上面的參數(shù)都定義完成后,咱們就得定義一下咱們的模型啦,TensorFlow提供了大量的模型可供使用,幾乎所有主流的機(jī)器學(xué)習(xí)的模型和深度學(xué)習(xí)相關(guān)的模型,TensorFlow幾乎實(shí)現(xiàn)全覆蓋了,具體咱們可以去他的官網(wǎng)查詢, 他的官網(wǎng)地址是: https://www.tensorflow.org/api_docs/python/tf ,記住在TensorFlow中,他的模型都在tf.estimator這個(gè)模塊中。因?yàn)檫@里是咱們講述用TensorFlow開發(fā)機(jī)器學(xué)習(xí)應(yīng)用的入門,咱們就選一個(gè)最簡(jiǎn)單的模型linear regressor模型來(lái)演示
linear_regressor = tf.estimator.LinearRegressor( feature_columns = feature_columns, optimizer = my_optimizer )這里咱們可以看出是如何初始化一個(gè)LinearRegressor對(duì)象的,同樣的,咱們可以看出來(lái)它初始化的時(shí)候也是需要傳遞feature_columns和optimizer這2個(gè)參數(shù)的,而這兩個(gè)參數(shù)正是咱們第二步中所初始化的,可以說(shuō)是環(huán)環(huán)相扣啊,哈哈,也可以看出咱們前面定義初始化的一個(gè)對(duì)象都是沒(méi)有多余的,都是要用到的。這兩個(gè)參數(shù)分別告訴了咱們的模型咱們數(shù)據(jù)columns的類型以及用什么optimizer來(lái)訓(xùn)練這2個(gè)信息。
第四步:數(shù)據(jù)源input_fn
既然咱們的原始數(shù)據(jù)準(zhǔn)備好了,模型也都定義好了,如果需要訓(xùn)練咱們的模型,咱們還差什么呢?對(duì)了就是將咱們的原始數(shù)據(jù)(這里的例子是dataframe)轉(zhuǎn)化成TensorFlow中的dataset,并將轉(zhuǎn)化后的data傳遞給咱們的模型,讓咱們之前定義的模型用這些數(shù)據(jù)去訓(xùn)練。這里應(yīng)該也是咱們用TensorFlow來(lái)建模的一個(gè)核心部分了,咱們先看代碼演示,然后我會(huì)逐個(gè)詳細(xì)解釋的
def my_input(features, targets, batch_size=500, shuffle=True, num_epochs=None): """ epochs: while trainning, in the case of steps is larger than the length of dataset, we set the epochs to None, which means repeat forever. However, in trainning process, we have the steps to control the total number of iterations. While in the case of making predictions of a given dataset, we must set epochs to 1 and shuffle to False. Because we only want the input function return the dataset once, otherwise the function will keep returnning the results forvere once and once again. shuffle: in the trainning process, in order to balance the dataset, we set it to True. However while in prediction process, we have to set it to False, which could help us to evaluate the outputs. For example, if the outputs are shuffled, we have no way to compare the outputs to our original lables. """ #convert panda dataframe to a dict of Numpy array features = {key:tf.multiply(np.array(value),1) for key,value in dict(features).items()} #construct a dataset ds = tf.data.Dataset.from_tensor_slices((features,targets)) ds = ds.batch(batch_size).repeat(num_epochs) if shuffle: ds = ds.shuffle(buffer_size = 10000) return ds這里有幾個(gè)核心的參數(shù)我需要解釋一下,首先f(wàn)eatures和target兩個(gè)參數(shù)很明顯就是咱們第一步中獲取的數(shù)據(jù),分別是用來(lái)訓(xùn)練這個(gè)模型的特征變量和label;重點(diǎn)這里解釋一下batch_size, shuffle 和 num_epochs這三個(gè)參數(shù),這三個(gè)參數(shù)在咱們TensorFlow的整個(gè)學(xué)習(xí)過(guò)程中都得用到,絕對(duì)的重點(diǎn),不容懷疑。首先咱們來(lái)看batch_size, 因?yàn)镾GD每一次都只會(huì)選用一條數(shù)據(jù)來(lái)計(jì)算咱們的gradient(訓(xùn)練模型),而咱們的數(shù)據(jù)具有很強(qiáng)的隨機(jī)性,那么就會(huì)導(dǎo)致咱們的模型最后很可能不可用,但是如果咱們每一個(gè)step都選用整個(gè)dataset來(lái)訓(xùn)練模型,又會(huì)導(dǎo)致咱們的訓(xùn)練過(guò)程非常漫長(zhǎng),那么聰明的人類就自然而然的想到了咱們可以每一次選用一定數(shù)量的數(shù)據(jù)來(lái)訓(xùn)練模型,一般的數(shù)據(jù)量咱們大致的范圍都是在10-10000之間,這種方式就成為mini-batch SGD, 在這里咱們就是采用了這種方式,咱們每一次選用500條數(shù)據(jù)來(lái)訓(xùn)練咱們的模型,這是通過(guò)設(shè)置batch_size的值來(lái)實(shí)現(xiàn)的。對(duì)于shuffle這個(gè)參數(shù)呢,也是為了打亂咱們的數(shù)據(jù)來(lái)進(jìn)行訓(xùn)練,最終的目的也是為了能幫助咱們訓(xùn)練出更加精確的模型,防止咱們的數(shù)據(jù)分布不合理導(dǎo)致模型有偏差,它里面的buffer_size的意思是先從ds中選中buffer_size個(gè)數(shù)據(jù)(這些數(shù)據(jù)暫時(shí)還是有序的,順序和ds中一樣),然后iterate的時(shí)候呢,就從這個(gè)buffer中隨機(jī)的選擇數(shù)據(jù)(這個(gè)選擇數(shù)據(jù)的過(guò)程就是無(wú)序的選擇了,實(shí)現(xiàn)了隨機(jī)的目的)。最后還有這個(gè)repeat(num_epochs)的函數(shù),首先repeat函數(shù)在training的過(guò)程中一定需要的,因?yàn)楫?dāng)咱們?cè)O(shè)置steps步數(shù)參數(shù)的時(shí)候,如果steps的總數(shù)要多余整個(gè)dataset的數(shù)據(jù)量的時(shí)候,那么這時(shí)候咱們一定得重復(fù)利用咱們的dataset來(lái)達(dá)到訓(xùn)練的目的,否則咱們的數(shù)據(jù)源的數(shù)據(jù)量不夠了,會(huì)出錯(cuò)的,這就是為什么需要repeat的原因,至于num_epochs是來(lái)控制重復(fù)的次數(shù)的,一般在training階段咱們將它設(shè)置成None, 意思就是無(wú)限循環(huán),知道training中的steps全部走完位置,如果在predict階段,咱們一般就設(shè)置成1,因?yàn)樵蹅凃?yàn)證階段不需要重復(fù)的,同樣的在predict的時(shí)候,數(shù)據(jù)源函數(shù)中的shuffle也要設(shè)置成False的,否則predict的結(jié)果都是亂序的,無(wú)法跟原來(lái)的數(shù)據(jù)進(jìn)行對(duì)比了。前面幾個(gè)參數(shù)在咱們模型訓(xùn)練過(guò)程中可以說(shuō)是最重要的參數(shù)了,這里說(shuō)的也比較多,所以一點(diǎn)得用心搞明白。
第五步:訓(xùn)練模型 training
既然上面咱們把模型的參數(shù)都設(shè)置好了,數(shù)據(jù)源也定義好了,那么接下來(lái)咱們的任務(wù)就是訓(xùn)練咱們定義的模型了,這個(gè)過(guò)程在代碼中是很簡(jiǎn)單的,但它內(nèi)部做的工作是很多的,它需要計(jì)算在每個(gè)維度(feature)上的gradient descent,知道它趨于0為止,它的計(jì)算細(xì)節(jié)我會(huì)在接下來(lái)的一個(gè)章節(jié)中展示出來(lái),咱們先看代碼
linear_regressor.train( input_fn = lambda:my_input(my_feature, targets), steps = 1000 )是不是很簡(jiǎn)單,咱們只需要將數(shù)據(jù)源函數(shù)作為參數(shù)傳遞給他,并且設(shè)置一個(gè)steps就可以了。這里input_fn我就不解釋了,簡(jiǎn)單說(shuō)一下steps,steps指的是咱們訓(xùn)練的步數(shù),咱們每計(jì)算一次gradient descent,就算一步,這里指咱們最多計(jì)算1000次,即使1000的時(shí)候gradient descent不等于0咱也停止咱的訓(xùn)練過(guò)程,然后咱們可以重新設(shè)置optimizer中的learning_rate來(lái)重新訓(xùn)練。
第六步:predict和evaluate
經(jīng)過(guò)前面五步后,咱們已經(jīng)訓(xùn)練出來(lái)了一個(gè)模型,那么接下來(lái)咱們需要用這個(gè)模型來(lái)預(yù)測(cè)一下數(shù)據(jù),并且看看它的效果,去evaluate一下這個(gè)模型。正常的情況下咱們會(huì)將數(shù)據(jù)split成training data 和 validation data,這里我為了方便,咱就直接用training data來(lái)演示如何predict還有如何evaluate咱們的模型。簡(jiǎn)單的代碼如下
#create a input function for predictionprediction_input_fn = lambda:my_input(my_feature,targets,shuffle=False,num_epochs=1)#predictionpredictions = linear_regressor.predict(input_fn = prediction_input_fn)predictions = np.array([item["predictions"][0] for item in predictions])#errors MSEmean_squared_error(targets,predictions)在咱們做prediction的時(shí)候,咱們也是需要數(shù)據(jù)源input_fn的,在prediction的時(shí)候,shuffle=False, num_epochs=1; 然后調(diào)用這個(gè)模型linear_regressor的predict方法,將數(shù)據(jù)源函數(shù)傳遞給他, 它返回的結(jié)果是一個(gè)list,這個(gè)list里面的element是一個(gè)dictionary,這個(gè)dictionary的key值“predictions”, value也是一個(gè)一個(gè)list,并且只有一個(gè)元素element,此element就是咱們要的結(jié)果。最后咱們要evaluate這個(gè)模型預(yù)測(cè)的結(jié)果,咱們有很多種方式可以驗(yàn)證,這里只展示了一個(gè)最簡(jiǎn)單的方式,就是計(jì)算咱們的target和prediction的方差,其實(shí)有很多很多種方式,在后面的章節(jié)我會(huì)慢慢介紹。
第七步:data visualization
好了,最后咱們來(lái)看一下根據(jù)咱們的學(xué)習(xí)的模型,咱們想看看它的具體的擬合的效果,這里就需要用一點(diǎn)之前咱們學(xué)習(xí)的數(shù)據(jù)可視化的內(nèi)容了,這里比較簡(jiǎn)單,咱們通過(guò)模型學(xué)習(xí)到的參數(shù),畫一條擬合線,然后在將數(shù)據(jù)畫到畫布上,坐標(biāo)分別是"total_rooms"和"house_median_price",然后通過(guò)scatter plot展示出來(lái)。代碼如下
sample = cali_housing_dataset_permutation.sample(n=300)x_0 = sample["total_rooms"].min()x_1 = sample["total_rooms"].max()linear_regressor.get_variable_names()#retrieve the name of the variableweights = linear_regressor.get_variable_value("linear/linear_model/total_rooms/weights")[0]#returns the value of variable given by namebias = linear_regressor.get_variable_value("linear/linear_model/bias_weights")#retruns the value of biasy_0 = weights*x_0+biasy_1 = weights*x_1+biasplt.plot([x_0,x_1],[y_0,y_1])#plot our regression lineplt.ylabel("median_house_value")#label the y Axesplt.xlabel("total_rooms")#label the x Axesplt.scatter(sample["total_rooms"],sample["median_house_value"])#plot a scatter plot from the sampleplt.show()結(jié)果如下
可以看得出來(lái),擬合的還不錯(cuò)。嘿嘿,關(guān)于模型訓(xùn)練過(guò)程的可視化,后面還有很多種,以后我慢慢說(shuō),例如:x坐標(biāo)是steps, y坐標(biāo)是loss, 也是非常常見的一種方式。
總結(jié)
今天完整的展示了用TensorFlow創(chuàng)建模型的整個(gè)過(guò)程,一直從data preparation到最后的evaluation,可以說(shuō)貫穿了TensorFlow開發(fā)機(jī)器學(xué)習(xí)應(yīng)用的整個(gè)過(guò)程。今天先用一個(gè)最簡(jiǎn)單的線性擬合例子展示這個(gè)過(guò)程,后面我還會(huì)展示更多的更加復(fù)雜的模型,例如:Logistic Regression, DNN, LSTM,等等等等。但是萬(wàn)變不離其宗,他們的基礎(chǔ)步驟都是上面的七個(gè)步驟。
總結(jié)
以上是生活随笔為你收集整理的linearregression_机器学习-TensorFlow建模过程 Linear Regression线性拟合应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 苹果软件更新设置(苹果软件更新设置在哪)
- 下一篇: 电脑内存加速小工具(电脑内存加速软件)