├── README.md ├── client.py └── wide_deep_train.py /README.md: -------------------------------------------------------------------------------- 1 | # tensorflow_serving_docker_deploy 2 | deploy machine learning model in tensorflow serving and docker 3 | -------------------------------------------------------------------------------- /client.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import tensorflow as tf 3 | from tensorflow_serving.apis import classification_pb2 4 | from tensorflow_serving.apis import prediction_service_pb2 5 | from grpc.beta import implementations 6 | 7 | # 8 | def get_input(a_list): 9 | 10 | def _float_feature(value): 11 | if value=='': 12 | value=0.0 13 | return tf.train.Feature(float_list=tf.train.FloatList(value=[float(value)])) 14 | 15 | def _byte_feature(value): 16 | return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) 17 | ''' 18 | age,workclass,fnlwgt,education,education_num,marital_status,occupation, 19 | relationship,race,gender,capital_gain,capital_loss,hours_per_week, 20 | native_country,income_bracket=a_list.strip('\n').strip('.').split(',') 21 | ''' 22 | feature_dict={ 23 | 'age':_float_feature(a_list[0]), 24 | 'workclass':_byte_feature(a_list[1].encode()), 25 | 'education':_byte_feature(a_list[3].encode()), 26 | 'education_num':_float_feature(a_list[4]), 27 | 'marital_status':_byte_feature(a_list[5].encode()), 28 | 'occupation':_byte_feature(a_list[6].encode()), 29 | 'relationship':_byte_feature(a_list[7].encode()), 30 | 'capital_gain':_float_feature(a_list[10]), 31 | 'capital_loss':_float_feature(a_list[11]), 32 | 'hours_per_week':_float_feature(a_list[12]), 33 | } 34 | model_input=tf.train.Example(features=tf.train.Features(feature=feature_dict)) 35 | return model_input 36 | 37 | def main(): 38 | channel = implementations.insecure_channel('10.211.44.8', 8500)#the ip and port of your server host 39 | stub = prediction_service_pb2.beta_create_PredictionService_stub(channel) 40 | 41 | # the test samples 42 | examples = [] 43 | f=open('adult.test','r') 44 | for line in f: 45 | line=line.strip('\n').strip('.').split(',') 46 | example=get_input(line) 47 | examples.append(example) 48 | 49 | request = classification_pb2.ClassificationRequest() 50 | request.model_spec.name = 'dnn'#your model_name which you set in docker container 51 | request.input.example_list.examples.extend(examples) 52 | 53 | response = stub.Classify(request, 20.0) 54 | 55 | for index in range(len(examples)): 56 | print(index) 57 | max_class = max(response.result.classifications[index].classes, key=lambda c: c.score) 58 | re=response.result.classifications[index] 59 | print(max_class.label,max_class.score)# the prediction class and probability 60 | if __name__=='__main__': 61 | main() 62 | -------------------------------------------------------------------------------- /wide_deep_train.py: -------------------------------------------------------------------------------- 1 | import parser 2 | import shutil 3 | 4 | import tensorflow as tf 5 | from wide_deep1 import build_model_columns 6 | 7 | _CSV_COLUMNS = [ 8 | 'age', 'workclass', 'fnlwgt', 'education', 'education_num', 9 | 'marital_status', 'occupation', 'relationship', 'race', 'gender', 10 | 'capital_gain', 'capital_loss', 'hours_per_week', 'native_country', 11 | 'income_bracket' 12 | ] 13 | 14 | _CSV_COLUMN_DEFAULTS = [[0], [''], [0], [''], [0], [''], [''], [''], [''], [''], 15 | [0], [0], [0], [''], ['']] 16 | 17 | 18 | def build_model_columns(): 19 | """Builds a set of wide and deep feature columns.""" 20 | # Continuous variable columns 21 | age = tf.feature_column.numeric_column('age') 22 | education_num = tf.feature_column.numeric_column('education_num') 23 | capital_gain = tf.feature_column.numeric_column('capital_gain') 24 | capital_loss = tf.feature_column.numeric_column('capital_loss') 25 | hours_per_week = tf.feature_column.numeric_column('hours_per_week') 26 | 27 | education = tf.feature_column.categorical_column_with_vocabulary_list( 28 | 'education', [ 29 | 'Bachelors', 'HS-grad', '11th', 'Masters', '9th', 'Some-college', 30 | 'Assoc-acdm', 'Assoc-voc', '7th-8th', 'Doctorate', 'Prof-school', 31 | '5th-6th', '10th', '1st-4th', 'Preschool', '12th']) 32 | 33 | marital_status = tf.feature_column.categorical_column_with_vocabulary_list( 34 | 'marital_status', [ 35 | 'Married-civ-spouse', 'Divorced', 'Married-spouse-absent', 36 | 'Never-married', 'Separated', 'Married-AF-spouse', 'Widowed']) 37 | 38 | relationship = tf.feature_column.categorical_column_with_vocabulary_list( 39 | 'relationship', [ 40 | 'Husband', 'Not-in-family', 'Wife', 'Own-child', 'Unmarried', 41 | 'Other-relative']) 42 | 43 | workclass = tf.feature_column.categorical_column_with_vocabulary_list( 44 | 'workclass', [ 45 | 'Self-emp-not-inc', 'Private', 'State-gov', 'Federal-gov', 46 | 'Local-gov', '?', 'Self-emp-inc', 'Without-pay', 'Never-worked']) 47 | 48 | # To show an example of hashing: 49 | occupation = tf.feature_column.categorical_column_with_hash_bucket( 50 | 'occupation', hash_bucket_size=1000) 51 | 52 | # Transformations. 53 | age_buckets = tf.feature_column.bucketized_column( 54 | age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65]) 55 | 56 | # Wide columns and deep columns. 57 | base_columns = [ 58 | education, marital_status, relationship, workclass, occupation, 59 | age_buckets, 60 | ] 61 | 62 | crossed_columns = [ 63 | tf.feature_column.crossed_column( 64 | ['education', 'occupation'], hash_bucket_size=1000), 65 | tf.feature_column.crossed_column( 66 | [age_buckets, 'education', 'occupation'], 67 | hash_bucket_size=1000), 68 | ] 69 | 70 | wide_columns = base_columns + crossed_columns 71 | 72 | deep_columns = [ 73 | age, 74 | education_num, 75 | capital_gain, 76 | capital_loss, 77 | hours_per_week, 78 | tf.feature_column.indicator_column(workclass), 79 | tf.feature_column.indicator_column(education), 80 | tf.feature_column.indicator_column(marital_status), 81 | tf.feature_column.indicator_column(relationship), 82 | # To show an example of embedding 83 | tf.feature_column.embedding_column(occupation, dimension=8), 84 | ] 85 | 86 | return wide_columns, deep_columns 87 | 88 | def input_fn(data_file, num_epochs, shuffle, batch_size): 89 | assert tf.gfile.Exists(data_file), ('no file named : ' + str(data_file)) 90 | 91 | def process_list_column(list_column): 92 | sparse_strings = tf.string_split(list_column, delimiter="|") 93 | return sparse_strings.values 94 | 95 | def parse_csv(value): 96 | columns = tf.decode_csv(value, record_defaults=_CSV_COLUMN_DEFAULTS) 97 | features = dict(zip(_CSV_COLUMNS, columns)) 98 | features['workclass'] = process_list_column([features['workclass']]) 99 | labels = tf.equal(features.pop('income_bracket'), '>50K') 100 | labels = tf.reshape(labels, [-1]) 101 | return features, labels 102 | 103 | dataset = tf.data.TextLineDataset(data_file) 104 | if shuffle: dataset = dataset.shuffle(buffer_size=5000) 105 | dataset = dataset.map(parse_csv) 106 | dataset = dataset.repeat(num_epochs) 107 | dataset = dataset.batch(batch_size) 108 | return dataset 109 | 110 | def build_estimator(model_dir): 111 | 112 | wide_columns,deep_columns=build_model_columns() 113 | run_config = tf.estimator.RunConfig().replace(session_config=tf.ConfigProto(device_count={'GPU': 0})) 114 | return tf.estimator.DNNLinearCombinedClassifier( 115 | model_dir=model_dir, 116 | n_classes=2, 117 | dnn_dropout=0.5, 118 | linear_feature_columns=wide_columns, 119 | dnn_feature_columns=deep_columns, 120 | dnn_hidden_units=[100,100,200], 121 | config=run_config) 122 | 123 | def main(): 124 | 125 | shutil.rmtree('model', ignore_errors=True) 126 | model = build_estimator('model') 127 | 128 | # Train and evaluate the model every `FLAGS.epochs_per_eval` epochs. 129 | for n in range(10// 2): 130 | model.train(input_fn=lambda: input_fn('adult.data', 2, True, 10)) 131 | results = model.evaluate(input_fn=lambda: input_fn('adult.test', 1, False, 100)) 132 | 133 | # Display evaluation metrics 134 | print('Results at epoch', (n + 1) * 2) 135 | print('-' * 20) 136 | 137 | for key in sorted(results): 138 | print('%s: %s' % (key, results[key])) 139 | 140 | wide_columns,deep_columns= build_model_columns() 141 | fs=wide_columns+deep_columns 142 | fs = tf.feature_column.make_parse_example_spec(fs) 143 | print(fs) 144 | serving_fn = tf.estimator.export.build_parsing_serving_input_receiver_fn(fs) 145 | print('>>>\n',serving_fn) 146 | export_dir = model.export_savedmodel('export',serving_fn,as_text=True) 147 | print(export_dir) 148 | 149 | 150 | def predict(): 151 | model = build_estimator('model') 152 | predictions = model.predict(input_fn=lambda: input_fn('adult.test', 1, False, 40)) 153 | file=open('predict_result.txt','w') 154 | ''' 155 | def get_input(a_list): 156 | def _float_feature(value): 157 | if value=='': 158 | value=0.0 159 | return tf.train.Feature(float_list=tf.train.FloatList(value=[float(value)])) 160 | 161 | def _byte_feature(value): 162 | return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) 163 | age,workclass,fnlwgt,education,education_num,marital_status,occupation, 164 | relationship,race,gender,capital_gain,capital_loss,hours_per_week,native_country,income_bracket 165 | feature_dict={ 166 | 'age':-_float_feature(age), 167 | 'age', 'workclass', 'fnlwgt', 'education', 'education_num', 168 | 'marital_status', 'occupation', 'relationship', 'race', 'gender', 169 | 'capital_gain', 'capital_loss', 'hours_per_week', 'native_country', 170 | 'income_bracket' 171 | } 172 | 173 | def predict_model(): 174 | predict_fn = tf.contrib.predictor.from_saved_model('export/1533442948') 175 | 176 | return 0 177 | ''' 178 | if __name__ == '__main__': 179 | tf.logging.set_verbosity(tf.logging.INFO) 180 | #FLAGS, unparsed = parser.parse_known_args() 181 | main() 182 | #tf.app.run(main=main, argv='1') 183 | --------------------------------------------------------------------------------