摘要:它們從文件中生成一個(gè)浮點(diǎn)型的二維數(shù)組,并用于饋送到神經(jīng)網(wǎng)絡(luò)。最后計(jì)算損失函數(shù),即計(jì)算預(yù)測價(jià)格和實(shí)際價(jià)格之間的差異,并添加正則化到損失函數(shù)中。現(xiàn)在我們在有一系列節(jié)點(diǎn),當(dāng)在會(huì)話中使用時(shí),每個(gè)節(jié)點(diǎn)計(jì)算損失函數(shù)對一個(gè)變量的梯度。
目前流行的深度學(xué)習(xí)框架 TensorFlow(TensorFlow 中文官方公眾號(hào)已于月初發(fā)布) 是以 C++為底層構(gòu)建的,但絕大多數(shù)人都在 Python 上使用 TensorFlow 來開發(fā)自己的模型。隨著 C++ API 的完善,直接使用 C++來搭建神經(jīng)網(wǎng)絡(luò)已經(jīng)成為可能,本文將向你介紹一種簡單的實(shí)現(xiàn)方法。
很多人都知道 TensorFlow 的核心是構(gòu)建在 C++之上的,但是這種深度學(xué)習(xí)框架的大多數(shù)功能只在 Python API 上才方便使用。
當(dāng)我寫上一篇文章的時(shí)候,我的目標(biāo)是僅使用 TensorFlow 中的 C++ API 和 CuDNN 來實(shí)現(xiàn)基本的深度神經(jīng)網(wǎng)絡(luò)(DNN)。在實(shí)踐中,我意識(shí)到在這個(gè)過程中我們忽略了很多東西。
注意,使用外部操作(exotic operations)訓(xùn)練神經(jīng)網(wǎng)絡(luò)是不可能的,你面臨的錯(cuò)誤最有可能就是缺少梯度運(yùn)算。目前我正在試圖將 Python 上的梯度運(yùn)算遷移到 C++上。
在本文中,我將展示如何使用 TensorFlow 在 C++ 上構(gòu)建深度神經(jīng)網(wǎng)絡(luò),并通過車齡、公里數(shù)和使用油品等條件為寶馬 1 系汽車進(jìn)行估價(jià)。目前,我們還沒有可用的 C++ 優(yōu)化器,所以你會(huì)看到訓(xùn)練代碼看起來不那么吸引人,但是我們會(huì)在未來加入的。
本文章遵從 TensorFlow 1.4 C++ API 官方指南:https://www.tensorflow.org/api_guides/cc/guide
代碼 GitHub:https://github.com/theflofly/dnn_tensorflow_cpp
安裝
我們會(huì)在 C++ 中運(yùn)行 TensorFlow 框架,我們需要嘗試使用已編譯的庫,但肯定有些人會(huì)因?yàn)榄h(huán)境的特殊性而遇到麻煩。從頭開始構(gòu)建 TensorFlow 將避免這些問題,同時(shí)確保使用的是版本的 API。
首先,你需要安裝 bazel 構(gòu)建工具,這里有安裝方法:https://docs.bazel.build/versions/master/install.html
在 OSX 上 brew 就足夠了:
brew install bazel
你需要從 TensorFlow 源文件開始構(gòu)建:
mkdir /path/tensorflow
cd /path/tensorflow
git clone https://github.com/tensorflow/tensorflow.git
隨后你需要進(jìn)行配置,如選擇是否使用 GPU,你需要這樣運(yùn)行配置腳本:
cd /path/tensorflow
./configure
現(xiàn)在我們要?jiǎng)?chuàng)建接收 TensorFlow 模型代碼的文件。請注意,第一次構(gòu)建需要花費(fèi)很長一段時(shí)間(10-15 分鐘)。非核心的 C++ TF 代碼在 /tensorflow/cc 中,這是我們創(chuàng)建模型文件的位置,我們也需要 BUILD 文件讓 bazel 可以構(gòu)建模型。
mkdir /path/tensorflow/model
cd /path/tensorflow/model
touch model.cc
touch BUILD
我們在 BUILD 文件中加入 bazel 指令:
load(
"http://tensorflow:tensorflow.bzl"
,?
"tf_cc_binary"
)
tf_cc_binary(
? ? name =?
"model"
,
? ? srcs = [
? ? ? ??
"model.cc"
,
? ? ],
? ? deps = [
? ? ? ??
"http://tensorflow/cc:gradients"
,
? ? ? ??
"http://tensorflow/cc:grad_ops"
,
? ? ? ??
"http://tensorflow/cc:cc_ops"
,
? ? ? ??
"http://tensorflow/cc:client_session"
,
? ? ? ??
"http://tensorflow/core:tensorflow"
? ? ],
)
基本上,它會(huì)使用 model.cc 構(gòu)建一個(gè)二進(jìn)制文件。現(xiàn)在,我們可以開始編寫自己的模型了。
讀取數(shù)據(jù)
這些數(shù)據(jù)從法國網(wǎng)站 leboncoin.fr 上摘取,隨后被清理和歸一化,并被存儲(chǔ)于 CSV 文件中。我們的目標(biāo)是讀取這些數(shù)據(jù)。經(jīng)歸一化的源數(shù)據(jù)被存儲(chǔ)在 CSV 文件的第一行,我們需要使用它們重構(gòu)神經(jīng)網(wǎng)絡(luò)輸出的價(jià)格。所以,我們創(chuàng)建 data_set.h 和 data_set.cc 文件來保持代碼清潔。它們從 CSV 文件中生成一個(gè)浮點(diǎn)型的二維數(shù)組,并用于饋送到神經(jīng)網(wǎng)絡(luò)。
data_set.h
using namespace std;
//?
Meta
?data used to normalize the data set.?
Useful
?to
// go back?
and
?forth between normalized data.
class
?
DataSetMetaData
?{
friend?
class
?
DataSet
;
private:
? float mean_km;
? float std_km;
? float mean_age;
? float std_age;
? float min_price;
? float max_price;
};
enum?
class
?
Fuel
?{
? ? DIESEL,
? ? GAZOLINE
};
class
?
DataSet
?{
public:
? //?
Construct
?a data set?
from
?the given csv file path.
??
DataSet
(string path) {
? ??
ReadCSVFile
(path);
? }
? // getters
? vector
return
?x_; }
? vector
return
?y_; }
? // read the given csv file?
and
?complete x_?
and
?y_
? void?
ReadCSVFile
(string path);
? // convert one csv line to a vector of float
? vector
ReadCSVLine
(string line);
? // normalize a human input using the data set metadata
? initializer_list
Fuel
?fuel, float age);
? // convert a price outputted by the DNN to a human price
? float output(float price);
private:
??
DataSetMetaData
?data_set_metadata;
? vector
? vector
};
data_set.cc
#include
#include
#include
#include
#include "data_set.h"
using namespace std;
void?
DataSet
::
ReadCSVFile
(string path) {
? ifstream file(path);
? stringstream buffer;
? buffer << file.rdbuf();
? string line;
? vector
??
while
(getline(buffer, line,?
" "
)) {
? ? lines.push_back(line);
? }
? // the first line contains the metadata
? vector
ReadCSVLine
(lines[
0
]);
? data_set_metadata.mean_km = metadata[
0
];
? data_set_metadata.std_km = metadata[
1
];
? data_set_metadata.mean_age = metadata[
2
];
? data_set_metadata.std_age = metadata[
3
];
? data_set_metadata.min_price = metadata[
4
];
? data_set_metadata.max_price = metadata[
5
];
? // the other lines contain the features?
for
?each car
??
for
?(int i =?
2
; i < lines.size(); ++i) {
? ? vector
ReadCSVLine
(lines[i]);
? ? x_.insert(x_.end(), features.begin(), features.begin() +?
3
);
? ? y_.push_back(features[
3
]);
? }
}
vector
DataSet
::
ReadCSVLine
(string line) {
? vector
? std::stringstream lineStream(line);
? std::string cell;
??
while
(std::getline(lineStream, cell,?
","
))
? {
? ? line_data.push_back(stod(cell));
? }
??
return
?line_data;
}
initializer_list
DataSet
::input(float km,?
Fuel
?fuel, float age) {
? km = (km - data_set_metadata.mean_km) / data_set_metadata.std_km;
? age = (age - data_set_metadata.mean_age) / data_set_metadata.std_age;
? float f = fuel ==?
Fuel
::DIESEL ? -
1.f
?:?
1.f
;
??
return
?{km, f, age};
}
float?
DataSet
::output(float price) {
??
return
?price * (data_set_metadata.max_price - data_set_metadata.min_price) + data_set_metadata.min_price;
}
我們必須在 bazel BUILD 文件中添加這兩個(gè)文件。
load(
"http://tensorflow:tensorflow.bzl"
,?
"tf_cc_binary"
)
tf_cc_binary(
? ? name =?
"model"
,
? ? srcs = [
? ? ? ??
"model.cc"
,
? ? ? ??
"data_set.h"
,
? ? ? ??
"data_set.cc"
? ? ],
? ? deps = [
? ? ? ??
"http://tensorflow/cc:gradients"
,
? ? ? ??
"http://tensorflow/cc:grad_ops"
,
? ? ? ??
"http://tensorflow/cc:cc_ops"
,
? ? ? ??
"http://tensorflow/cc:client_session"
,
? ? ? ??
"http://tensorflow/core:tensorflow"
? ? ],
)
構(gòu)建模型
第一步是讀取 CSV 文件,并提取出兩個(gè)張量,其中 x 是輸入,y 為預(yù)期的真實(shí)結(jié)果。我們使用之前定義的 DataSet 類。
CSV 數(shù)據(jù)集下載鏈接:https://github.com/theflofly/dnn_tensorflow_cpp/blob/master/normalized_car_features.csv
DataSet
?data_set(
"/path/normalized_car_features.csv"
);
Tensor
?x_data(
DataTypeToEnum
? ? ? ? ? ? ??
TensorShape
{static_cast
3
,?
3
});
copy_n(data_set.x().begin(), data_set.x().size(),
? ? ? ?x_data.flat
Tensor
?y_data(
DataTypeToEnum
? ? ? ? ? ? ??
TensorShape
{static_cast
1
});
copy_n(data_set.y().begin(), data_set.y().size(),?
? ? ? ?y_data.flat
要定義一個(gè)張量,我們需要知道它的類型和形狀。在 data_set 對象中,x 數(shù)據(jù)以向量的方式保存,所以我們將尺寸縮減為 3(每個(gè)保存三個(gè)特征)。隨后我們使用 std::copy_n 來從 data_set 對象中復(fù)制數(shù)據(jù)到 Tensor(一個(gè) Eigen::TensorMap)的底層數(shù)據(jù)結(jié)構(gòu)中。現(xiàn)在,我們有了數(shù)據(jù)和 TensorFlow 數(shù)據(jù)結(jié)構(gòu),是時(shí)候構(gòu)建模型了。
你可以輕易地調(diào)試一個(gè)張量:
LOG(INFO) << x_data.
DebugString
();
C ++ API 的獨(dú)特之處在于,您需要一個(gè) Scope 對象來保持構(gòu)建靜態(tài)計(jì)算圖的狀態(tài),并將該對象傳遞給每個(gè)操作。
Scope
?scope =?
Scope
::
NewRootScope
();
我們需要兩個(gè)占位符,x 包含特征,y 代表每輛車相應(yīng)的價(jià)格。
auto x =?
Placeholder
(scope, DT_FLOAT);
auto y =?
Placeholder
(scope, DT_FLOAT);
我們的網(wǎng)絡(luò)有兩個(gè)隱藏層,因此我們會(huì)有三個(gè)權(quán)重矩陣和三個(gè)偏置項(xiàng)向量。在 Python 中,它是由底層直接完成的,在 C++ 中你必須定義一個(gè)變量,隨后定義一個(gè) Assign 節(jié)點(diǎn)以為該變量分配一個(gè)默認(rèn)值。我們使用 RandomNormal 來初始化我們的變量,這會(huì)給我們一個(gè)服從正態(tài)分布的隨機(jī)值。
// weights init
auto w1 =?
Variable
(scope, {
3
,?
3
}, DT_FLOAT);
auto assign_w1 =?
Assign
(scope, w1,?
RandomNormal
(scope, {
3
,?
3
}, DT_FLOAT));
auto w2 =?
Variable
(scope, {
3
,?
2
}, DT_FLOAT);
auto assign_w2 =?
Assign
(scope, w2,?
RandomNormal
(scope, {
3
,?
2
}, DT_FLOAT));
auto w3 =?
Variable
(scope, {
2
,?
1
}, DT_FLOAT);
auto assign_w3 =?
Assign
(scope, w3,?
RandomNormal
(scope, {
2
,?
1
}, DT_FLOAT));
// bias init
auto b1 =?
Variable
(scope, {
1
,?
3
}, DT_FLOAT);
auto assign_b1 =?
Assign
(scope, b1,?
RandomNormal
(scope, {
1
,?
3
}, DT_FLOAT));
auto b2 =?
Variable
(scope, {
1
,?
2
}, DT_FLOAT);
auto assign_b2 =?
Assign
(scope, b2,?
RandomNormal
(scope, {
1
,?
2
}, DT_FLOAT));
auto b3 =?
Variable
(scope, {
1
,?
1
}, DT_FLOAT);
auto assign_b3 =?
Assign
(scope, b3,?
RandomNormal
(scope, {
1
,?
1
}, DT_FLOAT));
隨后我們使用 Tanh 作為激活函數(shù)來構(gòu)建三個(gè)層。
// layers
auto layer_1 =?
Tanh
(scope,?
Add
(scope,?
MatMul
(scope, x, w1), b1));
auto layer_2 =?
Tanh
(scope,?
Add
(scope,?
MatMul
(scope, layer_1, w2), b2));
auto layer_3 =?
Tanh
(scope,?
Add
(scope,?
MatMul
(scope, layer_2, w3), b3));
加入 L2 正則化。
// regularization
auto regularization =?
AddN
(scope,
? ? ? ? ? ? ? ? ? ? ? ? ?initializer_list<
Input
>{L2Loss(scope, w1),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?L2Loss(scope, w2),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?L2Loss(scope, w3)});
最后計(jì)算損失函數(shù),即計(jì)算預(yù)測價(jià)格和實(shí)際價(jià)格 y 之間的差異,并添加正則化到損失函數(shù)中。
// loss calculation
auto loss =?
Add
(scope,
? ? ? ? ? ? ? ??
ReduceMean
(scope,?
Square
(scope,?
Sub
(scope, layer_3, y)), {
0
,?
1
}),
? ? ? ? ? ? ? ??
Mul
(scope,?
Cast
(scope,?
0.01
, ?DT_FLOAT), regularization));
在這里,我們完成了前向傳播,現(xiàn)在該進(jìn)行反向傳播了。第一步是調(diào)用函數(shù)以在前向傳播操作的計(jì)算圖中加入梯度運(yùn)算。
// add the gradients operations to the graph
std::vector<
Output
> grad_outputs;
TF_CHECK_OK(
AddSymbolicGradients
(scope, {loss}, {w1, w2, w3, b1, b2, b3}, &grad_outputs));
所有的運(yùn)算都需要計(jì)算損失函數(shù)對每一個(gè)變量的導(dǎo)數(shù)并添加到計(jì)算圖中,我們初始化 grad_outputs 為一個(gè)空向量,它在 TensorFlow 會(huì)話打開時(shí)會(huì)將梯度傳入節(jié)點(diǎn),grad_outputs[0] 會(huì)提供損失函數(shù)對 w1 的導(dǎo)數(shù),grad_outputs[1] 提供損失函數(shù)對 w2 的導(dǎo)數(shù),這一過程會(huì)根據(jù) {w1, w2, w3, b1,b2, b3} 的順序,也是變量被傳遞到 AddSymbolicGradients 的順序進(jìn)行。
現(xiàn)在我們在 grad_outputs 有一系列節(jié)點(diǎn),當(dāng)在 TensorFlow 會(huì)話中使用時(shí),每個(gè)節(jié)點(diǎn)計(jì)算損失函數(shù)對一個(gè)變量的梯度。我們需要使用它來更新變量。所以,我們在每行放一個(gè)變量,使用梯度下降這個(gè)最簡單的方法來更新。
// update the weights?
and
?bias using gradient descent
auto apply_w1 =?
ApplyGradientDescent
(scope, w1,?
Cast
(scope,?
0.01
, ?DT_FLOAT), {grad_outputs[
0
]});
auto apply_w2 =?
ApplyGradientDescent
(scope, w2,?
Cast
(scope,?
0.01
, ?DT_FLOAT), {grad_outputs[
1
]});
auto apply_w3 =?
ApplyGradientDescent
(scope, w3,?
Cast
(scope,?
0.01
, ?DT_FLOAT), {grad_outputs[
2
]});
auto apply_b1 =?
ApplyGradientDescent
(scope, b1,?
Cast
(scope,?
0.01
, ?DT_FLOAT), {grad_outputs[
3
]});
auto apply_b2 =?
ApplyGradientDescent
(scope, b2,?
Cast
(scope,?
0.01
, ?DT_FLOAT), {grad_outputs[
4
]});
auto apply_b3 =?
ApplyGradientDescent
(scope, b3,?
Cast
(scope,?
0.01
, ?DT_FLOAT), {grad_outputs[
5
]});
Cast 操作實(shí)際上是學(xué)習(xí)速率的參數(shù),在這里是 0.01。
我們神經(jīng)網(wǎng)絡(luò)的計(jì)算圖已經(jīng)構(gòu)建完畢,現(xiàn)在可以打開一個(gè)會(huì)話并運(yùn)行該計(jì)算圖。基于 Python 的 Optimizers API 基本封裝了計(jì)算和應(yīng)用過程中的損失函數(shù)最小化方法。當(dāng) Optimizer API 可以接入 C++ 時(shí)我們就可以在這里使用它了。
我們初始化一個(gè)以 ClientSession 和一個(gè)以 Tensor 命名的輸出向量,用來接收網(wǎng)絡(luò)的輸出。
ClientSession
?session(scope);
std::vector<
Tensor
> outputs;
隨后在 Python 中調(diào)用 tf.global_variables_initializer() 就可以初始化變量,因?yàn)樵跇?gòu)建計(jì)算圖時(shí),所有變量的列表都是保留的。在 C++中,我們必須列出變量。每個(gè) RandomNormal 輸出會(huì)分配給 Assign 節(jié)點(diǎn)中定義的變量。
// init the weights?
and
?biases by running the assigns nodes once
TF_CHECK_OK(session.
Run
({assign_w1, assign_w2, assign_w3, assign_b1, assign_b2, assign_b3}, nullptr));
在這一點(diǎn)上,我們可以在訓(xùn)練數(shù)量內(nèi)循環(huán)地更新參數(shù),在我們的例子中是 5000 步。第一步是使用 loss 節(jié)點(diǎn)運(yùn)行前向傳播部分,輸出是網(wǎng)絡(luò)的損失。每 100 步我們都會(huì)記錄一次損失值,損失的減少是網(wǎng)絡(luò)成功運(yùn)行的標(biāo)志。隨后我們必須計(jì)算梯度節(jié)點(diǎn)并更新變量。我們的梯度節(jié)點(diǎn)是 ApplyGradientDescent 節(jié)點(diǎn)的輸入,所以運(yùn)行 apply_nodes 會(huì)首先計(jì)算梯度,隨后將其應(yīng)用到正確的變量上。
// training steps
for
?(int i =?
0
; i
5000
; ++i) {
? TF_CHECK_OK(session.
Run
({{x, x_data}, {y, y_data}}, {loss}, &outputs));
??
if
?(i %?
100
?==?
0
) {
? ? std::cout <
"Loss after "
?<< i <
" steps "
?<< outputs[
0
].Scalar
? }
? // nullptr because the output?
from
?the run?
is
?useless
? TF_CHECK_OK(session.
Run
({{x, x_data}, {y, y_data}}, {apply_w1, apply_w2, apply_w3, apply_b1, apply_b2, apply_b3, layer_3}, nullptr));
}
在網(wǎng)絡(luò)訓(xùn)練到這種程度后,我們可以嘗試預(yù)測汽車的價(jià)格了——進(jìn)行推斷。讓我們來嘗試預(yù)測一輛車齡為 7 年,里程 11 萬公里,柴油發(fā)動(dòng)機(jī)的寶馬 1 系轎車。為了這樣做我們需要運(yùn)行 layer_3 節(jié)點(diǎn),將汽車的數(shù)據(jù)輸入 x,這是一個(gè)前向傳播的步驟。因?yàn)槲覀冎斑\(yùn)行了 5000 步的訓(xùn)練,權(quán)重已經(jīng)得到了學(xué)習(xí),所以輸出的結(jié)果將不是隨機(jī)的。
我們不能直接使用汽車的屬性,因?yàn)槲覀兊纳窠?jīng)網(wǎng)絡(luò)是從歸一化屬性中學(xué)習(xí)的,所以數(shù)據(jù)必須經(jīng)過同樣的歸一化過程。DataSet 類有一個(gè) input 方法在 CSV 讀取器件處理數(shù)據(jù)集中的元數(shù)據(jù)。
// prediction using the trained neural net
TF_CHECK_OK(session.
Run
({{x, {data_set.input(
110000.f
,?
Fuel
::DIESEL,?
7.f
)}}}, {layer_3}, &outputs));
cout <
"DNN output: "
?<< *outputs[
0
].scalar
std::cout <
"Price predicted "
?<< data_set.output(*outputs[
0
].scalar
" euros"
?<< std::endl;
網(wǎng)絡(luò)的輸出值在 0 到 1 之間,data_set 的 output 方法還負(fù)責(zé)將數(shù)值從元數(shù)據(jù)轉(zhuǎn)換回人類可讀的數(shù)字。模型可以使用 bazel run -c opt //tensorflow/cc/models:model 命令來運(yùn)行,如果 TensorFlow 剛剛被編譯,你可以看到這樣形式的輸出:
Loss
?after?
0
?steps?
0.317394
Loss
?after?
100
?steps?
0.0503757
Loss
?after?
200
?steps?
0.0487724
Loss
?after?
300
?steps?
0.047366
Loss
?after?
400
?steps?
0.0460944
Loss
?after?
500
?steps?
0.0449263
Loss
?after?
600
?steps?
0.0438395
Loss
?after?
700
?steps?
0.0428183
Loss
?after?
800
?steps?
0.041851
Loss
?after?
900
?steps?
0.040929
Loss
?after?
1000
?steps?
0.0400459
Loss
?after?
1100
?steps?
0.0391964
Loss
?after?
1200
?steps?
0.0383768
Loss
?after?
1300
?steps?
0.0375839
Loss
?after?
1400
?steps?
0.0368152
Loss
?after?
1500
?steps?
0.0360687
Loss
?after?
1600
?steps?
0.0353427
Loss
?after?
1700
?steps?
0.0346358
Loss
?after?
1800
?steps?
0.0339468
Loss
?after?
1900
?steps?
0.0332748
Loss
?after?
2000
?steps?
0.0326189
Loss
?after?
2100
?steps?
0.0319783
Loss
?after?
2200
?steps?
0.0313524
Loss
?after?
2300
?steps?
0.0307407
Loss
?after?
2400
?steps?
0.0301426
Loss
?after?
2500
?steps?
0.0295577
Loss
?after?
2600
?steps?
0.0289855
Loss
?after?
2700
?steps?
0.0284258
Loss
?after?
2800
?steps?
0.0278781
Loss
?after?
2900
?steps?
0.0273422
Loss
?after?
3000
?steps?
0.0268178
Loss
?after?
3100
?steps?
0.0263046
Loss
?after?
3200
?steps?
0.0258023
Loss
?after?
3300
?steps?
0.0253108
Loss
?after?
3400
?steps?
0.0248298
Loss
?after?
3500
?steps?
0.0243591
Loss
?after?
3600
?steps?
0.0238985
Loss
?after?
3700
?steps?
0.0234478
Loss
?after?
3800
?steps?
0.0230068
Loss
?after?
3900
?steps?
0.0225755
Loss
?after?
4000
?steps?
0.0221534
Loss
?after?
4100
?steps?
0.0217407
Loss
?after?
4200
?steps?
0.0213369
Loss
?after?
4300
?steps?
0.0209421
Loss
?after?
4400
?steps?
0.020556
Loss
?after?
4500
?steps?
0.0201784
Loss
?after?
4600
?steps?
0.0198093
Loss
?after?
4700
?steps?
0.0194484
Loss
?after?
4800
?steps?
0.0190956
Loss
?after?
4900
?steps?
0.0187508
DNN output:?
0.0969611
Price
?predicted?
13377.7
?euros
這里的預(yù)測車價(jià)是 13377.7 歐元。每次預(yù)測的到的車價(jià)都不相同,甚至?xí)橛?8000-17000 之間。這是因?yàn)槲覀冎皇褂昧巳齻€(gè)屬性來描述汽車,而我們的的模型架構(gòu)也相對比較簡單。
正如之前所說的,C++ API 的開發(fā)仍在進(jìn)行中,我們希望在不久的將來,更多的功能可以加入進(jìn)來。?
原文鏈接:https://matrices.io/training-a-deep-neural-network-using-only-tensorflow-c/
歡迎加入本站公開興趣群商業(yè)智能與數(shù)據(jù)分析群
興趣范圍包括各種讓數(shù)據(jù)產(chǎn)生價(jià)值的辦法,實(shí)際應(yīng)用案例分享與討論,分析工具,ETL工具,數(shù)據(jù)倉庫,數(shù)據(jù)挖掘工具,報(bào)表系統(tǒng)等全方位知識(shí)
QQ群:81035754
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/4696.html
摘要:下圖總結(jié)了絕大多數(shù)上的開源深度學(xué)習(xí)框架項(xiàng)目,根據(jù)項(xiàng)目在的數(shù)量來評(píng)級(jí),數(shù)據(jù)采集于年月初。然而,近期宣布將轉(zhuǎn)向作為其推薦深度學(xué)習(xí)框架因?yàn)樗С忠苿?dòng)設(shè)備開發(fā)。該框架可以出色完成圖像識(shí)別,欺詐檢測和自然語言處理任務(wù)。 很多神經(jīng)網(wǎng)絡(luò)框架已開源多年,支持機(jī)器學(xué)習(xí)和人工智能的專有解決方案也有很多。多年以來,開發(fā)人員在Github上發(fā)布了一系列的可以支持圖像、手寫字、視頻、語音識(shí)別、自然語言處理、物體檢測的...
摘要:作為當(dāng)下最熱門的話題,等巨頭都圍繞深度學(xué)習(xí)重點(diǎn)投資了一系列新興項(xiàng)目,他們也一直在支持一些開源深度學(xué)習(xí)框架。八來自一個(gè)日本的深度學(xué)習(xí)創(chuàng)業(yè)公司,今年月發(fā)布的一個(gè)框架。 深度學(xué)習(xí)(Deep Learning)是機(jī)器學(xué)習(xí)中一種基于對數(shù)據(jù)進(jìn)行表征學(xué)習(xí)的方法,深度學(xué)習(xí)的好處是用 非 監(jiān)督式或半監(jiān)督式 的特征學(xué)習(xí)、分層特征提取高效算法來替代手工獲取特征(feature)。作為當(dāng)下最熱門的話題,Google...
摘要:首先是最頂層的抽象,這個(gè)里面最基礎(chǔ)的就是和,記憶中和的抽象是類似的,將計(jì)算結(jié)果和偏導(dǎo)結(jié)果用一個(gè)抽象類來表示了。不過,本身并沒有像其它兩個(gè)庫一樣提供,等模型的抽象類,因此往往不會(huì)直接使用去寫模型。 本文將從deep learning 相關(guān)工具庫的使用者角度來介紹下github上stars數(shù)排在前面的幾個(gè)庫(tensorflow, keras, torch, theano, skflow, la...
摘要:近日它們交鋒的戰(zhàn)場就是動(dòng)態(tài)計(jì)算圖,誰能在這場戰(zhàn)爭中取得優(yōu)勢,誰就把握住了未來用戶的流向。所以動(dòng)態(tài)框架對虛擬計(jì)算圖的構(gòu)建速度有較高的要求。動(dòng)態(tài)計(jì)算圖問題之一的多結(jié)構(gòu)輸入問題的高效計(jì) 隨著深度學(xué)習(xí)的發(fā)展,深度學(xué)習(xí)框架之間競爭也日益激烈,新老框架紛紛各顯神通,想要在廣大DeepLearner的服務(wù)器上占據(jù)一席之地。近日它們交鋒的戰(zhàn)場就是動(dòng)態(tài)計(jì)算圖,誰能在這場戰(zhàn)爭中取得優(yōu)勢,誰就把握住了未來用戶的流...
摘要:大家好,我是黃文堅(jiān),今天給大家講講深度學(xué)習(xí)。我們再來看看這兩個(gè)深度學(xué)習(xí)的網(wǎng)絡(luò),左邊是策略網(wǎng)絡(luò),我走到一步的時(shí)候,分析棋盤上每個(gè)位置有多大價(jià)值,給每個(gè)位置打一個(gè)分?jǐn)?shù)。可以說深度學(xué)習(xí)讓機(jī)器人擁有幾歲小孩拾起物體的能力。 大家好,我是黃文堅(jiān),今天給大家講講深度學(xué)習(xí)。我不講技術(shù)原理,講講技術(shù)應(yīng)用。深度學(xué)習(xí)是我們明略重要的研究方向,是未來實(shí)現(xiàn)很多令人驚嘆的功能的工具,也可以說是通向人工智能的必經(jīng)之路。...
閱讀 1410·2021-10-08 10:04
閱讀 732·2021-09-07 09:58
閱讀 2912·2019-08-30 15:55
閱讀 2423·2019-08-29 17:21
閱讀 2125·2019-08-28 18:04
閱讀 3074·2019-08-28 17:57
閱讀 714·2019-08-26 11:46
閱讀 2227·2019-08-23 17:20