动态 版块 发帖 消息 我的
ggdo
今天的学习,明天的成就!
 默认    精华  
shixld
29
在Flask开发RESTful后端时,前端请求会遇到跨域的问题。下面是解决方法。Python版本:3.5.1下载flask_cors包pip install flask-cors使用flask_cors的CORS,代码示例from flask_cors import * app = Flask(__name__) CORS(app, supports_credentials=True)如果还有其他问题可以查看flask_cors文档
 0  20天前
shixld
28
Cannot interpret feed_dict key as Tensor: Tensor Tensor("Placeholder_8:0", shape=(3, 3, 128, 256), dtype=float32) is not an element of this graph.后端我使用的是django框架,上传一张图片传入基于tensorflow的keras模型进行预测,重复预测时,报告上述错误.原因大概是第二次预测时,model底层tensorflow的session中还有数据.解决方法:在调用模型前面加一句 keras.backend.clear_session()
 0  20天前
shixld
28
1. 为什么选择Keras?Keras 是 Google 的一位工程师 François Chollet 开发的一个框架,可以帮助你在 Theano 上面进行快速原型开发。后来,这被扩展为 TensorFlow 也可以作为后端。并且最近,TensorFlow决定将其作为 contrib 文件中的一部分进行提供。Keras 被认为是构建神经网络的未来,以下是一些它流行的原因:轻量级和快速开发:Keras 的目的是在消除样板代码。几行 Keras 代码就能比原生的 TensorFlow 代码实现更多的功能。你也可以很轻松的实现 CNN 和 RNN,并且让它们运行在 CPU 或者 GPU 上面。框架的“赢者”:Keras 是一个API,运行在别的深度学习框架上面。这个框架可以是 TensorFlow 或者 Theano。Microsoft 也计划让 CNTK 作为 Keras 的一个后端。目前,神经网络框架世界是非常分散的,并且发展非常快。具体,你可以看看 Karpathy 的这个推文:想象一下,我们每年都要去学习一个新的框架,这是多么的痛苦。到目前为止,TensorFlow 似乎成为了一种潮流,并且越来越多的框架开始为 Keras 提供支持,它可能会成为一种标准。目前,Keras 是成长最快的一种深度学习框架。因为可以使用不同的深度学习框架作为后端,这也使得它成为了流行的一个很大的原因。你可以设想这样一个场景,如果你阅读到了一篇很有趣的论文,并且你想在你自己的数据集上面测试这个模型。让我们再次假设,你对TensorFlow 非常熟悉,但是对Theano了解的非常少。那么,你必须使用TensorFlow 对这个论文进行复现,但是这个周期是非常长的。但是,如果现在代码是采用Keras写的,那么你只要将后端修改为TensorFlow就可以使用代码了。这将是对社区发展的一个巨大的推动作用。2. 怎么安装Keras,并且把TensorFlow作为后端a) 依赖安装安装 h5py,用于模型的保存和载入:pip install h5py还有一些依赖包也要安装。pip install numpy scipypip install pillow如果你还没有安装TensorFlow,那么你可以按照这个教程先去安装TensorFlow。一旦,你安装完成了 TensorFlow,你只需要使用 pip 很容易的安装 Keras。sudo pip install keras使用以下命令来查看 Keras 版本。>>> import kerasUsing TensorFlow backend.>>> keras.__version__'2.0.4'一旦,Keras 被安装完成,你需要去修改后端文件,也就是去确定,你需要 TensorFlow 作为后端,还是 Theano 作为后端,修改的配置文件位于 ~/.keras/keras.json 。具体配置如下:{    "floatx": "float32",    "epsilon": 1e-07,    "backend": "tensorflow",    "image_data_format": "channels_last"}请注意,参数 image_data_format 是 channels_last ,也就是说这个后端是 TensorFlow。因为,在TensorFlow中图像的存储方式是[height, width, channels],但是在Theano中是完全不同的,也就是 [channels, height, width]。因此,如果你没有正确的设置这个参数,那么你模型的中间结果将是非常奇怪的。对于Theano来说,这个参数就是channels_first。那么,至此你已经准备好了,使用Keras来构建模型,并且把TensorFlow作为后端。3. Keras基础知识在Keras中主要的数据结构是 model ,该结构定义了一个完整的图。你可以向已经存在的图中加入任何的网络结构。import kerasKeras 有两种不同的建模方式:Sequential models:这种方法用于实现一些简单的模型。你只需要向一些存在的模型中添加层就行了。Functional API:Keras的API是非常强大的,你可以利用这些API来构造更加复杂的模型,比如多输出模型,有向无环图等等。在本文的下一节中,我们将学习Keras的Sequential models 和 Functional API的理论和实例。4. Keras Sequential models在这一部分中,我将来介绍Keras Sequential models的理论。我将快速的解释它是如何工作的,还会利用具体代码来解释。之后,我们将解决一个简单的线性回归问题,你可以在阅读的同时运行代码,来加深印象。以下代码是如何开始导入和构建序列模型。from keras.models import Sequentialmodels = Sequential()接下来我们可以向模型中添加 Dense(full connected layer),Activation,Conv2D,MaxPooling2D函数。from keras.layers import Dense, Activation, Conv2D, MaxPooling2D, Flatten, Dropoutmodel.add(Conv2D(64, (3,3), activation='relu', input_shape = (100,100,32)))# This ads a Convolutional layer with 64 filters of size 3 * 3 to the graph以下是如何将一些最流行的图层添加到网络中。我已经在卷积神经网络教程中写了很多关于图层的描述。1. 卷积层这里我们使用一个卷积层,64个卷积核,维度是3*3的,之后采用 relu 激活函数进行激活,输入数据的维度是 100*100*32。注意,如果是第一个卷积层,那么必须加上输入数据的维度,后面几个这个参数可以省略。model.add(Conv2D(64, (3,3), activation='relu', input_shape = (100,100,32)))2. MaxPooling 层指定图层的类型,并且指定赤的大小,然后自动完成赤化操作,酷毙了!model.add(MaxPooling2D(pool_size=(2,2)))3. 全连接层这个层在 Keras 中称为被称之为 Dense 层,我们只需要设置输出层的维度,然后Keras就会帮助我们自动完成了。model.add(Dense(256, activation='relu'))4. Dropoutmodel.add(Dropout(0.5))5. 扁平层model.add(Flatten())数据输入网络的第一层需要读入训练数据。因此我们需要去制定输入数据的维度。因此,input_shape参数被用于制定输入数据的维度大小。model.add(Conv2D(32, (3,3), activation='relu', input_shape=(224, 224, 3)))在这个例子中,数据输入的第一层是一个卷积层,输入数据的大小是 224*224*3 。以上操作就帮助你利用序列模型构建了一个模型。接下来,让我们学习最重要的一个部分。一旦你指定了一个网络架构,你还需要指定优化器和损失函数。我们在Keras中使用compile函数来达到这个功能。比如,在下面的代码中,我们使用 rmsprop 来作为优化器,binary_crossentropy 来作为损失函数值。model.compile(loss='binary_crossentropy', optimizer='rmsprop')如果你想要使用随机梯度下降,那么你需要选择合适的初始值和超参数:from keras.optimizers import SGDsgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)model.compile(loss='categorical_crossentropy', optimizer=sgd)现在,我们已经构建完了模型。接下来,让我们向模型中输入数据,在Keras中是通过 fit 函数来实现的。你也可以在该函数中指定 batch_size 和 epochs 来训练。model.fit(x_train, y_train, batch_size = 32, epochs = 10, validation_data(x_val, y_val))最后,我们使用 evaluate 函数来测试模型的性能。score = model.evaluate(x_test, y_test, batch_size = 32)这些就是使用序列模型在Keras中构建神经网络的具体操作步骤。现在,我们来构建一个简单的线性回归模型。4.1 实际例子讲解线性回归问题问题陈述在线性回归问题中,你可以得到很多的数据点,然后你需要使用一条直线去拟合这些离散点。在这个例子中,我们创建了100个离散点,然后用一条直线去拟合它们。a) 创建训练数据TrainX 的数据范围是 -1 到 1,TrainY 与 TrainX 的关系是3倍,并且我们加入了一些噪声点。import kerasfrom keras.models import Sequentialfrom keras.layers import Denseimport numpy as np trX = np.linspace(-1, 1, 101)trY = 3 * trX + np.random.randn(*trX.shape) * 0.33b) 构建模型首先我们需要构建一个序列模型。我们需要的只是一个简单的链接,因此我们只需要使用一个 Dense 层就够了,然后用线性函数进行激活。model = Sequential()model.add(Dense(input_dim=1, output_dim=1, init='uniform', activation='linear'))下面的代码将设置输入数据 x,权重 w 和偏置项 b。然我们来看看具体的初始化工作。如下:weights = model.layers[0].get_weights()w_init = weights[0][0][0]b_init = weights[1][0]print('Linear regression model is initialized with weights w: %.2f, b: %.2f' % (w_init, b_init)) ## Linear regression model is initialized with weight w: -0.03, b: 0.00现在,我们可以l利用自己构造的数据 trX 和 trY 来训练这个线性模型,其中 trY 是 trX 的3倍。因此,权重 w 的值应该是 3。我们使用简单的梯度下降来作为优化器,均方误差(MSE)作为损失值。如下:model.compile(optimizer='sgd', loss='mse')最后,我们使用 fit 函数来输入数据。model.fit(trX, trY, nb_epoch=200, verbose=1)在经过训练之后,我们再次打印权重:weights = model.layers[0].get_weights()w_final = weights[0][0][0]b_final = weights[1][0]print('Linear regression model is trained to have weight w: %.2f, b: %.2f' % (w_final, b_final))     ##Linear regression model is trained to have weight w: 2.94, b: 0.08正如你所看到的,在运行 200 轮之后,现在权重非常接近于 3。你可以将运行的轮数修改为区间 [100, 300] 之间,然后观察输出结构有什么变化。现在,你已经学会了利用很少的代码来构建一个线性回归模型,如果要构建一个相同的模型,在 TensorFlow 中需要用到更多的代码。5. 使用 Keras 保存和回复预训练的模型HDF5 二进制格式一旦你利用Keras完成了训练,你可以将你的网络保存在HDF5里面。当然,你需要先安装 h5py。HDF5 格式非常适合存储大量的数字收,并从 numpy 处理这些数据。比如,我们可以轻松的将存储在磁盘上的多TB数据集进行切片,就好像他们是真正的 numpy 数组一样。你还可以将多个数据集存储在单个文件中,遍历他们或者查看 .shape 和 .dtype 属性。如果你需要信心,那么告诉你,NASA也在使用 HDF5 进行数据存储。h5py 是python对HDF5 C API 的封装。几乎你可以用C在HDF5上面进行的任何操作都可以用python在h5py上面操作。保存权重如果你要保存训练好的权重,那么你可以直接使用 save_weights 函数。model.save_weights("my_model.h5")载入预训练权重如果你想要载入以前训练好的模型,那么你可以使用 load_weights 函数。model.load_weights('my_model_weights.h5')6. Keras API如果对于简单的模型和问题,那么序列模型是非常好的方式。但是如果你要构建一个现实世界中复杂的网络,那么你就需要知道一些功能性的API,在很多流行的神经网络中,我们都有一个最小的网络结构,完整的模型是根据这些最小的模型进行叠加完成的。这些基础的API可以让你一层一层的构建模型。因此,你只需要很少的代码就可以来构建一个完整的复杂神经网络。让我们来看看它是如何工作的。首先,你需要导入一些包。from keras.models import Model现在,你需要去指定输入数据,而不是在顺序模型中,在最后的 fit 函数中输入数据。这是序列模型和这些功能性的API之间最显著的区别之一。我们使用 input() 函数来申明一个 1*28*28 的张量。from keras.layers import Input## First, define the vision modulesdigit_input = Input(shape=(1, 28, 28))现在,让我们来利用API设计一个卷积层,我们需要指定要在在哪个层使用卷积网络,具体代码这样操作:x = Conv2D(64, (3, 3))(digit_input)x = Conv2D(64, (3, 3))(x)x = MaxPooling2D((2, 2))(x)out = Flatten()(x)最后,我们对于指定的输入和输出数据来构建一个模型。vision_model = Model(digit_input, out)当然,我们还需要指定损失函数,优化器等等。但这些和我们在序列模型中的操作一样,你可以使用 fit 函数和 compile 函数来进行操作。接下来,让我们来构建一个vgg-16模型,这是一个很大很“老”的模型,但是由于它的简洁性,它是一个很好的学习模型。6.1 使用Keras API开发VGG卷积神经网络VGG:VGG卷积神经网络是牛津大学在2014年提出来的模型。当这个模型被提出时,由于它的简洁性和实用性,马上成为了当时最流行的卷积神经网络模型。它在图像分类和目标检测任务中都表现出非常好的结果。在2014年的ILSVRC比赛中,VGG 在Top-5中取得了92.3%的正确率。 该模型有一些变种,其中最受欢迎的当然是 vgg-16,这是一个拥有16层的模型。你可以看到它需要维度是 224*224*3 的输入数据。*Vgg 16 architecture*让我们来写一个独立的函数来完整实现这个模型。img_input = Input(shape=input_shape)# Block 1x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)# Block 2x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)# Block 3x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)# Block 4x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)# Block 5x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)x = Flatten(name='flatten')(x)x = Dense(4096, activation='relu', name='fc1')(x)x = Dense(4096, activation='relu', name='fc2')(x)x = Dense(classes, activation='softmax', name='predictions')(x)我们可以将这个完整的模型,命名为 vgg16.py。在这个例子中,我们来运行 imageNet 数据集中的某一些数据来进行测试。具体代码如下:model = applications.VGG16(weights='imagenet')img = image.load_img('cat.jpeg', target_size=(224, 224))x = image.img_to_array(img)x = np.expand_dims(x, axis=0)x = preprocess_input(x)preds = model.predict(x)for results in decode_predictions(preds):    for result in results:        print('Probability %0.2f%% => [%s]' % (100*result[2], result[1]))正如你在图中看到的,模型会对图片中的物体进行一个识别预测。我们通过API构建了一个VGG模型,但是由于VGG是一个很简单的模型,所以并没有完全将API的能力开发出来。接下来,我们通过构建一个 SqueezeNet模型,来展示API的真正能力。6.2 使用Keras API构建并运行SqueezeNet卷积神经网络SequeezeNet 是一个非常了不起的网络架构,它的显著点不在于对正确性有多少的提高,而是减少了计算量。当SequeezeNet的正确性和AlexNet接近时,但是ImageNet上面的预训练模型的存储量小于5 MB,这对于在现实世界中使用CNN是非常有利的。SqueezeNet模型引入了一个 Fire模型,它由交替的 Squeeze 和 Expand 模块组成。*SqueezeNet fire module*现在,我们对 fire 模型进行多次复制,从而来构建完整的网络模型,具体如下:为了去构建这个网络,我们将利用API的功能首先来构建一个单独的 fire 模块。# Squeeze part of fire module with 1 * 1 convolutions, followed by Relux = Convolution2D(squeeze, (1, 1), padding='valid', name='fire2/squeeze1x1')(x)x = Activation('relu', name='fire2/relu_squeeze1x1')(x)#Expand part has two portions, left uses 1 * 1 convolutions and is called expand1x1 left = Convolution2D(expand, (1, 1), padding='valid', name='fire2/expand1x1')(x)left = Activation('relu', name='fire2/relu_expand1x1')(left)#Right part uses 3 * 3 convolutions and is called expand3x3, both of these are follow#ed by Relu layer, Note that both receive x as input as designed. right = Convolution2D(expand, (3, 3), padding='same', name='fire2/expand3x3')(x)right = Activation('relu', name='fire2/relu_expand3x3')(right)# Final output of Fire Module is concatenation of left and right. x = concatenate([left, right], axis=3, name='fire2/concat')为了重用这些代码,我们可以将它们转换成一个函数:sq1x1 = "squeeze1x1"exp1x1 = "expand1x1"exp3x3 = "expand3x3"relu = "relu_"WEIGHTS_PATH = "https://github.com/rcmalli/keras-squeezenet/releases/download/v1.0/squeezenet_weights_tf_dim_ordering_tf_kernels.h5"模块化处理sq1x1 = "squeeze1x1"exp1x1 = "expand1x1"exp3x3 = "expand3x3"relu = "relu_"def fire_module(x, fire_id, squeeze=16, expand=64):   s_id = 'fire' + str(fire_id) + '/'   x = Convolution2D(squeeze, (1, 1), padding='valid', name=s_id + sq1x1)(x)   x = Activation('relu', name=s_id + relu + sq1x1)(x)   left = Convolution2D(expand, (1, 1), padding='valid', name=s_id + exp1x1)(x)   left = Activation('relu', name=s_id + relu + exp1x1)(left)   right = Convolution2D(expand, (3, 3), padding='same', name=s_id + exp3x3)(x)   right = Activation('relu', name=s_id + relu + exp3x3)(right)   x = concatenate([left, right], axis=3, name=s_id + 'concat')return x现在,我们可以利用我们构建好的单独的 fire 模块,来构建完整的模型。x = Convolution2D(64, (3, 3), strides=(2, 2), padding='valid', name='conv1')(img_input)x = Activation('relu', name='relu_conv1')(x)x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool1')(x)x = fire_module(x, fire_id=2, squeeze=16, expand=64)x = fire_module(x, fire_id=3, squeeze=16, expand=64)x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool3')(x)x = fire_module(x, fire_id=4, squeeze=32, expand=128)x = fire_module(x, fire_id=5, squeeze=32, expand=128)x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool5')(x)x = fire_module(x, fire_id=6, squeeze=48, expand=192)x = fire_module(x, fire_id=7, squeeze=48, expand=192)x = fire_module(x, fire_id=8, squeeze=64, expand=256)x = fire_module(x, fire_id=9, squeeze=64, expand=256)x = Dropout(0.5, name='drop9')(x)x = Convolution2D(classes, (1, 1), padding='valid', name='conv10')(x)x = Activation('relu', name='relu_conv10')(x)x = GlobalAveragePooling2D()(x)out = Activation('softmax', name='loss')(x)model = Model(inputs, out, name='squeezenet')完整的网络模型我们放置在 squeezenet.py 文件里。我们应该先下载 imageNet 预训练模型,然后在我们自己的数据集上面进行训练和测试。下面的代码就是实现了这个功能:import numpy as npfrom keras_squeezenet import SqueezeNetfrom keras.applications.imagenet_utils import preprocess_input, decode_predictionsfrom keras.preprocessing import imagemodel = SqueezeNet()img = image.load_img('pexels-photo-280207.jpeg', target_size=(227, 227))x = image.img_to_array(img)x = np.expand_dims(x, axis=0)x = preprocess_input(x)preds = model.predict(x)all_results = decode_predictions(preds)for results in all_results:  for result in results:    print('Probability %0.2f%% => [%s]' % (100*result[2], result[1]))对于相同的一幅图预测,我们可以得到如下的预测概率。
 0  26天前
shixld
27
1:开发需要编写package.json文件,内部内容需有启动转换方式如 {"name": "vux-app", "version": "1.0.0", "description": "A Vue.js project", "author": "shenguangliang <shengl@dchealth.com>", "private": true, "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "lint": "eslint --ext .js,.vue src", "build": "node build/build.js" }, "dependencies": { "axios": "^0.17.1", "vux": "^2.8.0" }, "devDependencies": { "autoprefixer": "^7.1.2", "yaml-loader": "^0.4.0" }, "engines": { "node": ">= 4.0.0", "npm": ">= 3.0.0" }, "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] }2:安装nodejs,需注意安装正式版本(一般版本偶数)3:查看是否安装成功node -v4:CMD到项目的文件夹,输入npm i 安装需要的插件,如果需要改变下载网站地址,可以通过命令npm config set registry https://registry.npm.taobao.org进行修改5:到项目的根目录下运行 npm run dev启动项目,即可实现访问
 0  27天前
shixld
23
镜像使用方法(三种办法任意一种都能解决问题,建议使用第三种,将配置写死,下次用的时候配置还在):1.通过config命令npm config set registry https://registry.npm.taobao.org npm info underscore (如果上面配置正确这个命令会有字符串response)2.命令行指定npm --registry https://registry.npm.taobao.org info underscore 3.编辑 ~/.npmrc 加入下面内容registry = https://registry.npm.taobao.org
 0  27天前
shixld
26
1.变量声明let和const我们都是知道在ES6以前,var关键字声明变量。无论声明在何处,都会被视为声明在函数的最顶部(不在函数内即在全局作用域的最顶部)。这就是函数变量提升例如:function aa() { if(bool) { var test = 'hello man' } else { console.log(test) } }以上的代码实际上是:function aa() { var test // 变量提升 if(bool) { test = 'hello man' } else { //此处访问test 值为undefined console.log(test) } //此处访问test 值为undefined }所以不用关心bool是否为true or false。实际上,无论如何test都会被创建声明。接下来ES6主角登场:我们通常用let和const来声明,let表示变量、const表示常量。let和const都是块级作用域。怎么理解这个块级作用域?在一个函数内部,或者在一个代码块内部,说白了 {}大括号内的代码块即为let 和 const的作用域。看以下代码:function aa() { if(bool) { let test = 'hello man' } else { //test 在此处访问不到 console.log(test) } }let的作用域是在它所在当前代码块,但不会被提升到当前函数的最顶部。再来说说const。const name = 'lux' name = 'joe' //再次赋值此时会报错2.模板字符串es6模板字符简直是开发者的福音啊,解决了ES5在字符串功能上的痛点。第一个用途,基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定。 //es5 var name = 'lux' console.log('hello' + name) //es6 const name = 'lux' console.log(`hello ${name}`) //hello lux第二个用途,在ES5时我们通过反斜杠(\)来做多行字符串或者字符串一行行拼接。ES6反引号(``)直接搞定。复制代码// es5 var msg = "Hi \ man! " // es6 const template = `<div> <span>hello world</span> </div>`对于字符串es6当然也提供了很多厉害的方法。说几个常用的。复制代码// 1.includes:判断是否包含然后直接返回布尔值 let str = 'hahay' console.log(str.includes('y')) // true // 2.repeat: 获取字符串重复n次 let s = 'he' console.log(s.repeat(3)) // 'hehehe' //如果你带入小数, Math.floor(num) 来处理3.函数函数默认参数在ES5我们给函数定义参数默认值是怎么样? function action(num) { num = num || 200 //当传入num时,num为传入的值 //当没传入参数时,num即有了默认值200 return num }但细心观察的同学们肯定会发现,num传入为0的时候就是false, 此时num = 200 与我们的实际要的效果明显不一样ES6为参数提供了默认值。在定义函数时便初始化了这个参数,以便在参数没有被传递进去时使用。function action(num = 200) { console.log(num) } action() //200 action(300) //300箭头函数ES6很有意思的一部分就是函数的快捷写法。也就是箭头函数。箭头函数最直观的三个特点。    不需要function关键字来创建函数    省略return关键字    继承当前上下文的 this 关键字//例如: [1,2,3].map( x => x + 1 ) //等同于: [1,2,3].map((function(x){ return x + 1 }).bind(this))当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{};例如:var people = name => 'hello' + name //参数name就没有括号作为参考var people = (name, age) => { const fullName = 'h' + name return fullName } //如果缺少()或者{}就会报错4.拓展的对象功能对象初始化简写ES5我们对于对象都是以键值对的形式书写,是有可能出现键值对重名的。例如:function people(name, age) { return { name: name, age: age }; }键值对重名,ES6可以简写如下:function people(name, age) { return { name, age }; }ES6 同样改进了为对象字面量方法赋值的语法。ES5为对象添加方法:const people = { name: 'lux', getName: function() { console.log(this.name) } }ES6通过省略冒号与 function 关键字,将这个语法变得更简洁const people = { name: 'lux', getName () { console.log(this.name) } }ES6 对象提供了Object.assign()这个方法来实现浅复制。Object.assign()可以把任意多个源对象自身可枚举的属性拷贝给目标对象,然后返回目标对象。第一参数即为目标对象。在实际项目中,我们为了不改变源对象。一般会把目标对象传为{} const obj = Object.assign({}, objA, objB)5.更方便的数据访问--解构数组和对象是JS中最常用也是最重要表示形式。为了简化提取信息,ES6新增了解构,这是将一个数据结构分解为更小的部分的过程ES5我们提取对象中的信息形式如下:const people = { name: 'lux', age: 20 } const name = people.name const age = people.age console.log(name + ' --- ' + age)是不是觉得很熟悉,没错,在ES6之前我们就是这样获取对象信息的,一个一个获取。现在,解构能让我们从对象或者数组里取出数据存为变量,例如//对象 const people = { name: 'lux', age: 20 } const { name, age } = people console.log(`${name} --- ${age}`) //数组 const color = ['red', 'blue'] const [first, second] = color console.log(first) //'red' console.log(second) //'blue'6.Spread Operator 展开运算符ES6中另外一个好玩的特性就是Spread Operator 也是三个点儿...接下来就展示一下它的用途。组装对象或者数组//数组 const color = ['red', 'yellow'] const colorful = [...color, 'green', 'pink'] console.log(colorful) //[red, yellow, green, pink] //对象 const alp = { fist: 'a', second: 'b'} const alphabets = { ...alp, third: 'c' } console.log(alphabets) //{ "fist": "a", "second": "b", "third": "c" }有时候我们想获取数组或者对象除了前几项或者除了某几项的其他项const number = [1,2,3,4,5] const [first, ...rest] = number console.log(rest) //2,3,4,5 //对象 const user = { username: 'lux', gender: 'female', age: 19, address: 'peking' } const { username, ...rest } = user console.log(rest) //{"address": "peking", "age": 19, "gender": "female" }对于 Object 而言,还可以用于组合成新的 Object 。(ES2017 stage-2 proposal) 当然如果有重复的属性名,右边覆盖左边const first = { a: 1, b: 2, c: 6, } const second = { c: 3, d: 4 } const total = { ...first, ...second } console.log(total) // { a: 1, b: 2, c: 3, d: 4 }7.import 和 exportimport导入模块、export导出模块//全部导入 import people from './example' //有一种特殊情况,即允许你将整个模块当作单一对象进行导入 //该模块的所有导出都会作为对象的属性存在 import * as example from "./example.js" console.log(example.name) console.log(example.age) console.log(example.getName()) //导入部分 import {name, age} from './example' // 导出默认, 有且只有一个默认 export default App // 部分导出 export class App extend Component {};以前有人问我,导入的时候有没有大括号的区别是什么。下面是我在工作中的总结:1.当用export default people导出时,就用 import people 导入(不带大括号)2.一个文件里,有且只能有一个export default。但可以有多个export。3.当用export name 时,就用import { name }导入(记得带上大括号)4.当一个文件里,既有一个export default people, 又有多个export name 或者 export age时,导入就用 import people, { name, age } 5.当一个文件里出现n多个 export 导出很多模块,导入时除了一个一个导入,也可以用import * as example8. Promise    在promise之前代码过多的回调或者嵌套,可读性差、耦合度高、扩展性低。通过Promise机制,扁平化的代码机构,大大提高了代码可读性;用同步编程的方式来编写异步代码,保存线性的代码逻辑,极大的降低了代码耦合性而提高了程序的可扩展性。说白了就是用同步的方式去写异步代码。发起异步请求setTimeout(function() { console.log(1) }, 0); new Promise(function executor(resolve) { console.log(2); for( var i=0 ; i<10000 ; i++ ) { i == 9999 && resolve(); } console.log(3); }).then(function() { console.log(4); }); console.log(5);9.Generators生成器( generator)是能返回一个迭代器的函数。生成器函数也是一种函数,最直观的表现就是比普通的function多了个星号*,在其函数体内可以使用yield关键字,有意思的是函数会在每个yield后暂停。这里生活中有一个比较形象的例子。咱们到银行办理业务时候都得向大厅的机器取一张排队号。你拿到你的排队号,机器并不会自动为你再出下一张票。也就是说取票机“暂停”住了,直到下一个人再次唤起才会继续吐票。OK。说说迭代器。当你调用一个generator时,它将返回一个迭代器对象。这个迭代器对象拥有一个叫做next的方法来帮助你重启generator函数并得到下一个值。next方法不仅返回值,它返回的对象具有两个属性:done和value。value是你获得的值,done用来表明你的generator是否已经停止提供值。继续用刚刚取票的例子,每张排队号就是这里的value,打印票的纸是否用完就这是这里的done。// 生成器 function *createIterator() { yield 1; yield 2; yield 3; } // 生成器能像正规函数那样被调用,但会返回一个迭代器 let iterator = createIterator(); console.log(iterator.next().value); // 1 console.log(iterator.next().value); // 2 console.log(iterator.next().value); // 3那生成器和迭代器又有什么用处呢?围绕着生成器的许多兴奋点都与异步编程直接相关。异步调用对于我们来说是很困难的事,我们的函数并不会等待异步调用完再执行,你可能会想到用回调函数,(当然还有其他方案比如Promise比如Async/await)。生成器可以让我们的代码进行等待。就不用嵌套的回调函数。使用generator可以确保当异步调用在我们的generator函数运行一下行代码之前完成时暂停函数的执行。那么问题来了,咱们也不能手动一直调用next()方法,你需要一个能够调用生成器并启动迭代器的方法。就像这样子的function run(taskDef) { //taskDef即一个生成器函数 // 创建迭代器,让它在别处可用 let task = taskDef(); // 启动任务 let result = task.next(); // 递归使用函数来保持对 next() 的调用 function step() { // 如果还有更多要做的 if (!result.done) { result = task.next(); step(); } } // 开始处理过程 step(); }
 0  29天前
shixld
136
steve shi:客户端负载均衡:基于客户端的负载均衡,简单的说就是在客户端程序里面,自己设定一个调度算法,在向服务器发起请求的时候,先执行调度算法计算出向哪台服务器发起请求,然后再发起请求给服务器。特点:1:由客户端内部程序实现,不需要额外的负载均衡器软硬件投入。2:程序内部需要解决业务服务器不可用的问题,服务器故障对应用程序的透明度小。3:程序内部需要解决业务服务器压力过载的问题。使用场景:1:可以选择为初期简单的负载均衡方案,和DNS负载均衡一样。2:比较适合于客户端具有成熟的调度库函数,算法以及API等3:毕竟适合对服务器入流量较大的业务,如HTTP POST文件上传,FTP文件上传,Memcache大流量写入。4:可以结合其他负载均衡方案进行架构。
 1  34天前
admin
56
1、RoundRobinRule(轮询模式)public class RoundRobinRule extends AbstractLoadBalancerRule roundRobin方式轮询选择server 轮询index,选择index对应位置的server 该策略也是ribbon的默认策略application.ymlstores: ribbon: listOfServers: www.ggdo.cn,www.ggdo.net,www.tdwen.comSpringCloudRibbonApplication.java@SpringBootApplication @EnableDiscoveryClient @RestController public class SpringCloudRibbonApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudRibbonApplication.class, args); } @Autowired private LoadBalancerClient loadBalancer; @RequestMapping(value="static") public String staticRibbon(){ ServiceInstance instance = loadBalancer.choose("stores"); URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort())); System.out.println(storesUri); return "static"; } }连续请求6次执行结果:http://www.ggdo.cn:80http://www.ggdo.net:80http://www.tdwen.com:80http://www.ggdo.cn:80http://www.ggdo.net:80http://www.tdwen.com:802、RandomRule(随机策略)public class RandomRule extends AbstractLoadBalancerRule 随机选择一个server 在index上随机,选择index对应位置的server。在配置文件application.yml加入NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRulestores: ribbon: listOfServers: www.baidu.com,www.jalja.org,www.163.org #随机 NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule在SpringCloudRibbonApplication.java 中加入@Bean public IRule ribbonRule() { return new RandomRule();//这里配置策略,和配置文件对应 }执行6次的结果:http://www.ggdo.cn:80http://www.ggdo.cn:80http://www.ggdo.cn:80http://www.ggdo.net:80http://www.ggdo.cn:80http://www.tdwen.com:803、BestAvailableRule(并发量)public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule 选择一个最小的并发请求的server 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server在配置文件application.yml加入NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule在SpringCloudRibbonApplication.java 中加入@Bean public IRule ribbonRule() { return new BestAvailableRule();//这里配置策略,和配置文件对应 }执行6次的结果:http://www.ggdo.cn:80http://www.ggdo.cn:80http://www.ggdo.cn:80http://www.ggdo.cn:80http://www.ggdo.cn:80http://www.ggdo.cn:804、AvailabilityFilteringRule(服务器状态)public class AvailabilityFilteringRule extends PredicateBasedRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态5、WeightedResponseTimeRule(根据响应时间)public class WeightedResponseTimeRule extends RoundRobinRule 根据响应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。6、RetryRule(根据策略+重试)public class RetryRule extends AbstractLoadBalancerRule 对选定的负载均衡策略机上重试机制。 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server7、ZoneAvoidanceRule(Zone状态+服务状态)public class ZoneAvoidanceRule extends PredicateBasedRule 复合判断server所在区域的性能和server的可用性选择server 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。
 0  35天前
admin
46
负载均衡(Load Balance): 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。1、服务端负载均衡:客户端请求到负载均衡服务器,负载均衡服务器根据自身的算法将该请求转给某台真正提供业务的服务器,该服务器将响应数据给负载均衡服务器,负载均衡服务器最后将数据返回给客服端。(nginx)2、客服端负载均衡:基于客户端的负载均衡,简单的说就是在客户端程序里面,自己设定一个调度算法,在向服务器发起请求的时候,先执行调度算法计算出向哪台服务器发起请求,然后再发起请求给服务器。(Ribbon)基于客户端负载均衡的特点:由客户端内部程序实现,不需要额外的负载均衡器软硬件投入。程序内部需要解决业务服务器不可用的问题,服务器故障对应用程序的透明度小。程序内部需要解决业务服务器压力过载的问题。
 0  35天前
admin
32
Hystrix默认的超时时间是1秒,如果超过这个时间尚未响应,将会进入fallback代码。而首次请求往往会比较慢(因为Spring的懒加载机制,要实例化一些类),这个响应时间可能就大于1秒了解决方案有三种,以feign为例。方法一hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000该配置是让Hystrix的超时时间改为5秒方法二hystrix.command.default.execution.timeout.enabled: false该配置,用于禁用Hystrix的超时时间方法三feign.hystrix.enabled: false该配置,用于索性禁用feign的hystrix。该做法除非一些特殊场景,不推荐使用。
 0  35天前
guest
这是登录的故事~
我的小伙伴
网站所属 GGDO
© 2016-2018 GGDO
2018-05-23 15:09:06,Processed in 1.38126 second(s).
网站所属 GGDO