Git Product home page Git Product logo

wy1iu / sphereface Goto Github PK

View Code? Open in Web Editor NEW
1.6K 105.0 545.0 8.22 MB

Implementation for <SphereFace: Deep Hypersphere Embedding for Face Recognition> in CVPR'17.

License: MIT License

MATLAB 0.49% Shell 0.30% CMake 1.18% Makefile 0.27% HTML 0.08% CSS 0.10% Jupyter Notebook 57.87% C++ 33.15% Python 4.05% Cuda 2.47% Dockerfile 0.03%
face-recognition caffe sphereface cvpr-2017 face-detection angular-softmax deep-learning

sphereface's Introduction

SphereFace: Deep Hypersphere Embedding for Face Recognition

By Weiyang Liu, Yandong Wen, Zhiding Yu, Ming Li, Bhiksha Raj and Le Song

License

SphereFace is released under the MIT License (refer to the LICENSE file for details).

Update

  • 2022.4.10: If you are looking for an easy-to-use and well-performing PyTorch implementation of SphereFace, we now have it! Check out our official SphereFace PyTorch re-implementation here.

  • 2018.8.14: We recommand an interesting ECCV 2018 paper that comprehensively evaluates SphereFace (A-Softmax) on current widely used face datasets and their proposed noise-controlled IMDb-Face dataset. Interested users can try to train SphereFace on their IMDb-Face dataset. Take a look here.

  • 2018.5.23: A new SphereFace+ that explicitly enhances the inter-class separability has been introduced in our technical report. Check it out here. Code is released here.

  • 2018.2.1: As requested, the prototxt files for SphereFace-64 are released.

  • 2018.1.27: We updated the appendix of our SphereFace paper with useful experiments and analysis. Take a look here. The content contains:

    • The intuition of removing the last ReLU;
    • Why do we want to normalize the weights other than because we need more geometric interpretation?
    • Empirical experiment of zeroing out the biases;
    • More 2D visualization of A-Softmax loss on MNIST;
    • Angular Fisher score for evaluating the angular feature discriminativeness, which is a new and straightforward evluation metric other than the final accuracy.
    • Experiments of SphereFace on MegaFace with different convolutional layers;
    • The annealing optimization strategy for A-Softmax loss;
    • Details of the 3-patch ensemble strategy in MegaFace challenge;
  • 2018.1.20: We updated some resources to summarize the current advances in angular margin learning. Take a look here.

Contents

  1. Introduction
  2. Citation
  3. Requirements
  4. Installation
  5. Usage
  6. Models
  7. Results
  8. Video Demo
  9. Note
  10. Third-party re-implementation
  11. Resources for angular margin learning

Introduction

The repository contains the entire pipeline (including all the preprocessings) for deep face recognition with SphereFace. The recognition pipeline contains three major steps: face detection, face alignment and face recognition.

SphereFace is a recently proposed face recognition method. It was initially described in an arXiv technical report and then published in CVPR 2017. The most up-to-date paper with more experiments can be found at arXiv or here. To facilitate the face recognition research, we give an example of training on CAISA-WebFace and testing on LFW using the 20-layer CNN architecture described in the paper (i.e. SphereFace-20).

In SphereFace, our network architecures use residual units as building blocks, but are quite different from the standrad ResNets (e.g., BatchNorm is not used, the prelu replaces the relu, different initializations, etc). We proposed 4-layer, 20-layer, 36-layer and 64-layer architectures for face recognition (details can be found in the paper and prototxt files). We provided the 20-layer architecure as an example here. If our proposed architectures also help your research, please consider to cite our paper.

SphereFace achieves the state-of-the-art verification performance (previously No.1) in MegaFace Challenge under the small training set protocol.

Citation

If you find SphereFace useful in your research, please consider to cite:

@InProceedings{Liu_2017_CVPR,
  title = {SphereFace: Deep Hypersphere Embedding for Face Recognition},
  author = {Liu, Weiyang and Wen, Yandong and Yu, Zhiding and Li, Ming and Raj, Bhiksha and Song, Le},
  booktitle = {The IEEE Conference on Computer Vision and Pattern Recognition (CVPR)},
  year = {2017}
}

Our another closely-related previous work in ICML'16 (more):

@InProceedings{Liu_2016_ICML,
  title = {Large-Margin Softmax Loss for Convolutional Neural Networks},
  author = {Liu, Weiyang and Wen, Yandong and Yu, Zhiding and Yang, Meng},
  booktitle = {Proceedings of The 33rd International Conference on Machine Learning},
  year = {2016}
}

Requirements

  1. Requirements for Matlab
  2. Requirements for Caffe and matcaffe (see: Caffe installation instructions)
  3. Requirements for MTCNN (see: MTCNN - face detection & alignment) and Pdollar toolbox (see: Piotr's Image & Video Matlab Toolbox).

Installation

  1. Clone the SphereFace repository. We'll call the directory that you cloned SphereFace as SPHEREFACE_ROOT.

    git clone --recursive https://github.com/wy1iu/sphereface.git
  2. Build Caffe and matcaffe

    cd $SPHEREFACE_ROOT/tools/caffe-sphereface
    # Now follow the Caffe installation instructions here:
    # http://caffe.berkeleyvision.org/installation.html
    make all -j8 && make matcaffe

Usage

After successfully completing the installation, you are ready to run all the following experiments.

Part 1: Preprocessing

Note: In this part, we assume you are in the directory $SPHEREFACE_ROOT/preprocess/

  1. Download the training set (CASIA-WebFace) and test set (LFW) and place them in data/.

    mv /your_path/CASIA_WebFace  data/
    ./code/get_lfw.sh
    tar xvf data/lfw.tgz -C data/

    Please make sure that the directory of data/ contains two datasets.

  2. Detect faces and facial landmarks in CAISA-WebFace and LFW datasets using MTCNN (see: MTCNN - face detection & alignment).

    # In Matlab Command Window
    run code/face_detect_demo.m

    This will create a file dataList.mat in the directory of result/.

  3. Align faces to a canonical pose using similarity transformation.

    # In Matlab Command Window
    run code/face_align_demo.m

    This will create two folders (CASIA-WebFace-112X96/ and lfw-112X96/) in the directory of result/, containing the aligned face images.

Part 2: Train

Note: In this part, we assume you are in the directory $SPHEREFACE_ROOT/train/

  1. Get a list of training images and labels.

    mv ../preprocess/result/CASIA-WebFace-112X96 data/
    # In Matlab Command Window
    run code/get_list.m
    

    The aligned face images in folder CASIA-WebFace-112X96/ are moved from preprocess folder to train folder. A list CASIA-WebFace-112X96.txt is created in the directory of data/ for the subsequent training.

  2. Train the sphereface model.

    ./code/sphereface_train.sh 0,1

    After training, a model sphereface_model_iter_28000.caffemodel and a corresponding log file sphereface_train.log are placed in the directory of result/sphereface/.

Part 3: Test

Note: In this part, we assume you are in the directory $SPHEREFACE_ROOT/test/

  1. Get the pair list of LFW (view 2).

    mv ../preprocess/result/lfw-112X96 data/
    ./code/get_pairs.sh

    Make sure that the LFW dataset andpairs.txt in the directory of data/

  2. Extract deep features and test on LFW.

    # In Matlab Command Window
    run code/evaluation.m

    Finally we have the sphereface_model.caffemodel, extracted features pairs.mat in folder result/, and accuracy on LFW like this:

    fold 1 2 3 4 5 6 7 8 9 10 AVE
    ACC 99.33% 99.17% 98.83% 99.50% 99.17% 99.83% 99.17% 98.83% 99.83% 99.33% 99.30%

Models

  1. Visualizations of network architecture (tools from ethereon):
    • SphereFace-20: link
  2. Model file

Results

  1. Following the instruction, we go through the entire pipeline for 5 times. The accuracies on LFW are shown below. Generally, we report the average but we release the model-3 here.

    Experiment #1 #2 #3 (released) #4 #5
    ACC 99.24% 99.20% 99.30% 99.27% 99.13%
  2. Other intermediate results:

Video Demo

SphereFace Demo

Please click the image to watch the Youtube video. For Youku users, click here.

Details:

  1. It is an open-set face recognition scenario. The video is processed frame by frame, following the same pipeline in this repository.
  2. Gallery set consists of 6 identities. Each main character has only 1 gallery face image. All the detected faces are included in probe set.
  3. There is no overlap between gallery set and training set (CASIA-WebFace).
  4. The scores between each probe face and gallery set are computed by cosine similarity. If the maximal score of a probe face is smaller than a pre-definded threshold, the probe face would be considered as an outlier.
  5. Main characters are labeled by boxes with different colors. ( #ff0000Rachel, #ffff00Monica, #ff80ffPhoebe, #00ffffJoey, #0000ffChandler, #00ff00Ross)

Note

  1. Backward gradient

    • In this implementation, we did not strictly follow the equations in paper. Instead, we normalize the scale of gradient. It can be interpreted as a varying strategy for learning rate to help converge more stably. Similar idea and intuition also appear in normalized gradients and projected gradient descent.
    • More specifically, if the original gradient of f w.r.t x can be written as df/dx = coeff_w * w + coeff_x * x, we use the normalized version [df/dx] = (coeff_w * w + coeff_x * x) / norm_wx to perform backward propragation, where norm_wx is sqrt(coeff_w^2 + coeff_x^2). The same operation is also applied to the gradient of f w.r.t w.
    • In fact, you do not necessarily need to use the original gradient, since the original gradient sometimes is not an optimal design. One important criterion for modifying the backprop gradient is that the new "gradient" (strictly speaking, it is not a gradient anymore) need to make the objective value decrease stably and consistently. (In terms of some failure cases for gradient-based back-prop, I recommand a great talk by Shai Shalev-Shwartz)
    • If you use the original gradient to do the backprop, you could still make it work but may need different lambda settings, iteration number and learning rate decay strategy.
  2. Lambda and Note for training (When the loss becomes 87)

  3. According to recent advances, using feature normalization with a tunable scaling parameter s can significantly improve the performance of SphereFace on MegaFace challenge

  4. Difficulties in convergence - When you encounter difficulties in convergence (it may appear if you use SphereFace in another dataset), usually there are a few easy ways to address it.

    • First, try to use large mini-batch size.
    • Second, try to use PReLU instead of ReLU.
    • Third, increase the width and depth of our network.
    • Fourth, try to use better initialization. For example, use the pretrained model from the original softmax loss (it is also equivalent to finetuning).
    • Last and the most effective thing you could try is to change the hyper-parameters for lambda_min, lambda and its decay speed.

Third-party re-implementation

Resources for angular margin learning

L-Softmax loss and SphereFace present a promising framework for angular representation learning, which is shown very effective in deep face recognition. We are super excited that our works has inspired many well-performing methods (and loss functions). We list a few of them for your potential reference (not very up-to-date):

To evaluate the effectiveness of the angular margin learning method, you may consider to use the angular Fisher score proposed in the Appendix E of our SphereFace Paper.

Disclaimer: Some of these methods may not necessarily be inspired by us, but we still list them due to its relevance and excellence.

Contact

Weiyang Liu and Yandong Wen

Questions can also be left as issues in the repository. We will be happy to answer them.

sphereface's People

Contributors

wy1iu avatar ydwen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sphereface's Issues

Why don't you use BatchNorm layers in training nets?

In CenterFace and your SphereFace, your net models are both based on ResNets. But I noticed that neither of you use any BatchNorm layers (which differ from original resnets). I tried to add BatchNorm layers back. but got bad results (loss only converged to about 3.5).
So I'm really curious why BatchNorm layers are not good here. Any idea to explain this?

训练的收敛问题

完全按照步骤要求进行训练,唯一的区别是限于只有单个6G显存的980T,只能单GPU以128的batchsize进行训练。始终不能收敛,请问这是batchsize过小引起的收敛问题吗? 谢谢!

annotation and code doesn't match

// 1 / (-|x|) * (sign_3 * (24 * cos_theta_quartic - 8 * cos_theta_quadratic - 1) +

comment describes coeff_x as
1 / (-|x|) * (sign_3 * (24 * cos_theta_quartic - 8 * cos_theta_quadratic - 1) + sign_4) * x
where the operator before sign_4_data is add

while in your code
Dtype coeff_x = (Dtype)1. / (-x_norm_data[i]) * (sign_3_data[i * N_ + j] *
((Dtype)24. * cos_theta_quartic_data[i * N_ + j] -
(Dtype)8. * cos_theta_quadratic_data[i * N_ + j] - (Dtype)1.) -
sign_4_data[i * N_ + j]);

the operator before sign_4_data is minus

So which one is right? By the way, could you describe more details about how to deduce the derivative? I only get the right coeff_w while coeff_x is too difficult to deduce.

question about gradient calculation with respect to weight

In Margin Inner Product, the gradient with respect to weight is very simple:

  // Gradient with respect to weight
  if (this->param_propagate_down_[0]) {
    caffe_cpu_gemm<Dtype>(CblasTrans, CblasNoTrans, N_, K_, M_, (Dtype)1.,
        top_diff, bottom_data, (Dtype)1., this->blobs_[0]->mutable_cpu_diff());
  }

But in large margin softmax, the gradient calcuation is much more complex...

Can you please tell me how to simplify the gradient calcuation?
I failed to derive it ...

Accuracy on LFW dataset

Hi,@wy1iu,i used the 20 layers network trained on casita dataset and extract feature on lfw dataset by concate original face image and flip face image features and finally get 98.97% accuracy, is is normal? I write a 64 layers network according to your paper and finally get 98.88% accuracy, why the deeper network get a worse result?

Is loss 4.x?

Hi, actually, follow your instruction, after 28000 iterations, the loss decrease to 4.x. So, my question is one model can be used correct, what loss should be decreased to? Or, I should reset the max iterations, 10000 or 200000?
Thank you

Experiments on larger datasets

Hi guys,
I tested A-Softmax loss on CASIA dataset and it really does well, reaching a ~99% performance on lfw without careful tuning. But when I switch to use the MS-Celeb-1M datasets for training(roughly cleaned, 98.8% lfw with Lighten CNN), either the 28-layer net nor the 64-layer net seems not to converge. The 64-layer net is the same as mentioned in your paper.
Have you tried A-Softmax in such large dataset? I am still trying to tune my net but have no idea why it doesn't converge.

Question regarding paper

I really grateful that @wy1iu release the code. You and @ydwen are really pushing the Face-Verification forward.

I have some question regarding the paper and the code:

  1. What is the major change between L-SoftMax and A-SoftMax. For the equation it look like that in L-SoftMax weight are transformed to norm of weights and in A-SofrMax weight are transformed to normalized weight, right? If this is true, the main motivation was section 3.3 in Large-Margin Softmax Loss for Convolutional Neural Networks?
  2. Could you explain how did you choose function ψ (which replace cos(θ))?
  3. In both paper you use Taylor Series of cos(mθ) (Eq. 7 in Large Margin), right? What was the idea behind using different degree of series based on margin value? Why not using same for all margin?
  4. Here is my intuition behind this both paper: in fact we just scale the output from Linear layer by matrix of ones with different numbers (<1) on target classes. Both paper propose different method of scaling (with theoretical explanation). I think that maybe there is possible to make implementation which would just use scale matrix. I must think about it as there are many non-linear operation here.
  5. I was thinking about using CenterLoss but using cosine similarity. But then I realized than it is equivalent to SoftMax layer without bias (and SoftMax also compare features to other class center as well, not only target, so it make features even better). Do you agree with my interpretation?

SphereFace-64 and Baseline learning

I have two question:

  1. In weight initialization of released model you use sometimes xavier, sometimes gaussion. Any reason why? I have implemented this network in PyTorch and xavier for all layer works well for all network configuration expect 64 model (model diverge). And I'm searching reason why it does not work, maybe because of not mixed initialization? I checked other init method and non of them is working.

  2. I would like to learn baseline model using pure SoftMax. Did you add any layer between embedding (size 512) and classification layer (size num_class), like PReLu or Dropout? I have learned model (20) without adding anything, but it overfitt ( I split data to train/val set).

About the video demo

It is said only one image is registered for each person (could be the face detected for the first time), so in this case can I ask whether it is an open set test demo? E.g. the similarity between the registered face and the test titled one is always larger than the pre-set threshold (recognized as the same person). It seems once the face is detected, the recognition result is always right. Looking forward to your reply.

Mirroring and Multi-patch approach

Hi,

in the figures of your papers you can see that the 3-patch net outperforms the one patch net and you say that the 3-patch feature vector is formed by concatenating the feature vectors of each patch. However, you do not say in your paper how these patches are computed. Do you use a different alignment strategy and train a new net on each type of aligned images or do you introduce a small offset and extract the 3-patch features by just transforming the original image a bit and computing the features with the original net?
Furthermore I get better results when not concatenating the features of the mirrored image. Has anyone experimented on that (patch selection/(not) mirroring) ?

About preprocess code

Hello,
Your previous submit use MTCNNv2 as the preprocessing algorithm.
However, the latest submit change to MTCNNv1.
Is there any reason for this change?
Which version is used in your paper?

Thanks very much.

finetuning, fc6 layer initialization

first , i train my model using original softmax
then, i want to finetune it using a-softmax
i intend to initialize the a-softmax's fc6 layer param using the original softmax, but the log says that they don't have the same number of param blobs, I found that margin inner product layer has no bias param blob.
i tried xavier initialization , but when i freeze the layers before fc6 and only learn fc6, the loss cannot converge .Do i have to relax the lr of the layers before fc6?

Loss always stays around 9.3

Loss always stays around 9.3, not down
I set the learning rate to 0.01 and 0.06, and loss didn't converge???
How does the training network need to be modified?????
How is the training parameter set?????
Hope to get your help!!thanks!!
@wdwen

About the gradient on W

@wy1iu @ydwen
In your forward code, you set w to be w' (w' = w/||w||). But in the backward code, you just use ∂E/∂w' as the gradient of w. Actually it should be ∂E/∂w' * ∂w'/∂W, is it a bug?

Is lambda equivalent to smaller m?

From the form of the loss function, I think adding the lambda can be seen as using smaller m. I have plotted the curve of lambda=5, m=4 and find that it is approximately m=1.5.
image

Is my thought right?

Gamma and power settings for lambda?

Hi wy1iu,

Asoftmax is a great work.I have some questions about how to set gamma and power for lambda.
Using the settings in your prototxt
(
base: 1000
gamma: 0.12
power: 1
lambda_min: 5
)
lambda will drop very quickly to lambda_min, is it really possible to converge?
what is the best way to setting these for different networks and different size of training data?

Thanks.

something wrong with your weight_diff calculation

In sphereface, margin_inner_product_layer.cpp, line 277-278
you get gradient with respect to w using the same formula regardless of m: caffe_cpu_gemm(CblasTrans, CblasNoTrans, N_, K_, M_, (Dtype)1., top_diff, bottom_data, (Dtype)1., this->blobs_[0]->mutable_cpu_diff()); but

whereas in LargeMargin_softmax_loss, largemargin_inner_product_layer.cpp, line 263-356 you get gradient with respect to w according to m.

Can you tell me why?
Thanks.

why the result of sphereface on the tSNE doesn't perform better than lcnn?

I test the 20 layers sphereface network on my own database,then test the features on tSNE that generate by sphereface.But the result on tSNE doesn't perform better than the lcnn model.However it perform better than lcnn models(I trained) on lfw database.The sphereface net I had used is trained on MSceleb database and test on lfw database gets 98.65% acc.why the result of sphereface on the tSNE doesn't perform better than lcnn? Do you have test it on tSNE?

question about feature normalize

hello,
there are some paper normalize the features before input Softmax layer, and I think it's make sense because
(1)it will make the feature space more dense which suit for hyperplane to do classification.
(2)all feature be normalized will give larger gradients to hard samples.

I also think these ideas don't conflict with sphereface which depend on angular margin.
Do i think it right? and have you did such experiment?

Results from default config

Hi --

What are the results (eg LFW accuracy) that we should expect when running this code as described in the README? I don't have MATLAB so I'll need to run w/ a different face detection/alignment pipeline, so I want to see how much error is introduced by my variant.

Thanks

Implementation questions

Are you able to explain a couple of bits about the implementation of the margin_inner_product_layer?

  1. What is lambda_? It looks like it's a constant that decreases w/ the iterations, but doesn't seem to be mentioned in the paper. ** Edit: Looks like you mix x'w and margin(x'w) via (margin(x'w) + lambda_ * x'w) / (1 + lambda_) where lambda_ decreases exponentially w/ iterations. Is that right? **

  2. What is the type parameter? (eg. SINGLE, DOUBLE, TRIPLE, QUADRUPLE) I'm guessing this is how you set the value of m from the paper? ** Edit: I gather these are ways of implementing the margin for m={1,2,3,4}. Any particular reason why you implemented this way? Numerical stability? **

Thanks

A-softmax loss with 64 layer?

First of all thank you for your open code. You have developed a 20-layer Sphereface framework, and Is it necessary to study the 64-layer? Which of the two is better?

loss =87.3

Hi, when I trained the sphereface-27 with my dataset, I always run into a problem:loss=87.33, and my prototxt as shown below:

layer {
name: "fc6-"
type: "MarginInnerProduct"
bottom: "fc5"
bottom: "label"
top: "fc6"
top: "lambda"
param {
lr_mult: 1
decay_mult: 1
}
margin_inner_product_param {
num_output: 11954
type: QUADRUPLE
weight_filler {
type: "xavier"
}
base: 10
gamma: 2e-05
power: 1
iteration: 0
lambda_min: 5
}
}

I0922 23:43:59.428972 192876 solver.cpp:219] Iteration 7000 (0.325212 iter/s, 307.492s/100 iters), loss = 10.0837
I0922 23:43:59.429009 192876 solver.cpp:238] Train net output #0: accuracy = 0.574219
I0922 23:43:59.429015 192876 solver.cpp:238] Train net output #1: lambda = 8.77178
I0922 23:43:59.429021 192876 solver.cpp:238] Train net output #2: softmax_loss = 10.0837 (* 1 = 10.0837 loss)
I0922 23:43:59.429025 192876 sgd_solver.cpp:105] Iteration 7000, lr = 1e-05
I0922 23:45:04.017473 192883 data_layer.cpp:73] Restarting data prefetching from start.
I0922 23:49:06.527763 192876 solver.cpp:219] Iteration 7100 (0.325632 iter/s, 307.096s/100 iters), loss = 7.03009
I0922 23:49:06.527886 192876 solver.cpp:238] Train net output #0: accuracy = 0.6875
I0922 23:49:06.527894 192876 solver.cpp:238] Train net output #1: lambda = 8.75641
I0922 23:49:06.527901 192876 solver.cpp:238] Train net output #2: softmax_loss = 7.03009 (* 1 = 7.03009 loss)
I0922 23:49:06.527905 192876 sgd_solver.cpp:105] Iteration 7100, lr = 1e-05
I0922 23:54:13.578683 192876 solver.cpp:219] Iteration 7200 (0.325682 iter/s, 307.048s/100 iters), loss = 8.27169
I0922 23:54:13.578783 192876 solver.cpp:238] Train net output #0: accuracy = 0.65625
I0922 23:54:13.578791 192876 solver.cpp:238] Train net output #1: lambda = 8.74111
I0922 23:54:13.578797 192876 solver.cpp:238] Train net output #2: softmax_loss = 8.27169 (* 1 = 8.27169 loss)
I0922 23:54:13.578801 192876 sgd_solver.cpp:105] Iteration 7200, lr = 1e-05
I0922 23:59:20.621175 192876 solver.cpp:219] Iteration 7300 (0.325691 iter/s, 307.039s/100 iters), loss = 12.1695
I0922 23:59:20.621300 192876 solver.cpp:238] Train net output #0: accuracy = 0.617188
I0922 23:59:20.621309 192876 solver.cpp:238] Train net output #1: lambda = 8.72585
I0922 23:59:20.621316 192876 solver.cpp:238] Train net output #2: softmax_loss = 12.1695 (* 1 = 12.1695 loss)
I0922 23:59:20.621321 192876 sgd_solver.cpp:105] Iteration 7300, lr = 1e-05
I0923 00:04:27.686278 192876 solver.cpp:219] Iteration 7400 (0.325667 iter/s, 307.062s/100 iters), loss = 10.945
I0923 00:04:27.686388 192876 solver.cpp:238] Train net output #0: accuracy = 0.664062
I0923 00:04:27.686394 192876 solver.cpp:238] Train net output #1: lambda = 8.71065
I0923 00:04:27.686416 192876 solver.cpp:238] Train net output #2: softmax_loss = 10.945 (* 1 = 10.945 loss)
I0923 00:04:27.686421 192876 sgd_solver.cpp:105] Iteration 7400, lr = 1e-05
I0923 00:09:29.417439 192876 solver.cpp:448] Snapshotting to binary proto file /home/unique/data-face/face_model/WT_sphereface27-40_iter_7500.caffemodel
I0923 00:09:31.971767 192876 sgd_solver.cpp:273] Snapshotting solver state to binary proto file /home/unique/data-face/face_model/WT_sphereface27-40_iter_7500.solverstate
I0923 00:09:35.155453 192876 solver.cpp:219] Iteration 7500 (0.325239 iter/s, 307.466s/100 iters), loss = 10.7305
I0923 00:09:35.155522 192876 solver.cpp:238] Train net output #0: accuracy = 0.644531
I0923 00:09:35.155529 192876 solver.cpp:238] Train net output #1: lambda = 8.6955
I0923 00:09:35.155535 192876 solver.cpp:238] Train net output #2: softmax_loss = 10.7305 (* 1 = 10.7305 loss)
I0923 00:09:35.155540 192876 sgd_solver.cpp:105] Iteration 7500, lr = 1e-05
I0923 00:14:42.234946 192876 solver.cpp:219] Iteration 7600 (0.325652 iter/s, 307.076s/100 iters), loss = 12.6641
I0923 00:14:42.235061 192876 solver.cpp:238] Train net output #0: accuracy = 0.652344
I0923 00:14:42.235069 192876 solver.cpp:238] Train net output #1: lambda = 8.6804
I0923 00:14:42.235076 192876 solver.cpp:238] Train net output #2: softmax_loss = 12.6641 (* 1 = 12.6641 loss)
I0923 00:14:42.235080 192876 sgd_solver.cpp:105] Iteration 7600, lr = 1e-05
I0923 00:19:49.294009 192876 solver.cpp:219] Iteration 7700 (0.325674 iter/s, 307.056s/100 iters), loss = 13.261
I0923 00:19:49.294123 192876 solver.cpp:238] Train net output #0: accuracy = 0.617188
I0923 00:19:49.294131 192876 solver.cpp:238] Train net output #1: lambda = 8.66536
I0923 00:19:49.294138 192876 solver.cpp:238] Train net output #2: softmax_loss = 13.261 (* 1 = 13.261 loss)
I0923 00:19:49.294142 192876 sgd_solver.cpp:105] Iteration 7700, lr = 1e-05
I0923 00:24:56.366257 192876 solver.cpp:219] Iteration 7800 (0.32566 iter/s, 307.069s/100 iters), loss = 13.8046
I0923 00:24:56.366369 192876 solver.cpp:238] Train net output #0: accuracy = 0.628906
I0923 00:24:56.366377 192876 solver.cpp:238] Train net output #1: lambda = 8.65037
I0923 00:24:56.366386 192876 solver.cpp:238] Train net output #2: softmax_loss = 13.8046 (* 1 = 13.8046 loss)
I0923 00:24:56.366391 192876 sgd_solver.cpp:105] Iteration 7800, lr = 1e-05
I0923 00:30:03.426719 192876 solver.cpp:219] Iteration 7900 (0.325672 iter/s, 307.057s/100 iters), loss = 14.3722
I0923 00:30:03.426854 192876 solver.cpp:238] Train net output #0: accuracy = 0.640625
I0923 00:30:03.426863 192876 solver.cpp:238] Train net output #1: lambda = 8.63543
I0923 00:30:03.426870 192876 solver.cpp:238] Train net output #2: softmax_loss = 14.3722 (* 1 = 14.3722 loss)
I0923 00:30:03.426877 192876 sgd_solver.cpp:105] Iteration 7900, lr = 1e-05
I0923 00:35:05.096544 192876 solver.cpp:448] Snapshotting to binary proto file /home/unique/data-face/face_model/WT_sphereface27-40_iter_8000.caffemodel
I0923 00:35:07.648367 192876 sgd_solver.cpp:273] Snapshotting solver state to binary proto file /home/unique/data-face/face_model/WT_sphereface27-40_iter_8000.solverstate
I0923 00:35:10.833468 192876 solver.cpp:219] Iteration 8000 (0.325305 iter/s, 307.403s/100 iters), loss = 17.3922
I0923 00:35:10.833523 192876 solver.cpp:238] Train net output #0: accuracy = 0.648438
I0923 00:35:10.833528 192876 solver.cpp:238] Train net output #1: lambda = 8.62054
I0923 00:35:10.833534 192876 solver.cpp:238] Train net output #2: softmax_loss = 17.3922 (* 1 = 17.3922 loss)
I0923 00:35:10.833539 192876 sgd_solver.cpp:105] Iteration 8000, lr = 1e-05
I0923 00:40:17.756762 192876 solver.cpp:219] Iteration 8100 (0.325818 iter/s, 306.92s/100 iters), loss = 17.3765
I0923 00:40:17.756888 192876 solver.cpp:238] Train net output #0: accuracy = 0.644531
I0923 00:40:17.756896 192876 solver.cpp:238] Train net output #1: lambda = 8.6057
I0923 00:40:17.756903 192876 solver.cpp:238] Train net output #2: softmax_loss = 17.3765 (* 1 = 17.3765 loss)
I0923 00:40:17.756908 192876 sgd_solver.cpp:105] Iteration 8100, lr = 1e-05
I0923 00:45:24.701261 192876 solver.cpp:219] Iteration 8200 (0.325795 iter/s, 306.941s/100 iters), loss = 17.4908
I0923 00:45:24.701335 192876 solver.cpp:238] Train net output #0: accuracy = 0.625
I0923 00:45:24.701341 192876 solver.cpp:238] Train net output #1: lambda = 8.59092
I0923 00:45:24.701349 192876 solver.cpp:238] Train net output #2: softmax_loss = 17.4908 (* 1 = 17.4908 loss)
I0923 00:45:24.701354 192876 sgd_solver.cpp:105] Iteration 8200, lr = 1e-05
I0923 00:50:31.609172 192876 solver.cpp:219] Iteration 8300 (0.325834 iter/s, 306.905s/100 iters), loss = 21.0124
I0923 00:50:31.609232 192876 solver.cpp:238] Train net output #0: accuracy = 0.625
I0923 00:50:31.609238 192876 solver.cpp:238] Train net output #1: lambda = 8.57618
I0923 00:50:31.609246 192876 solver.cpp:238] Train net output #2: softmax_loss = 21.0124 (* 1 = 21.0124 loss)
I0923 00:50:31.609249 192876 sgd_solver.cpp:105] Iteration 8300, lr = 1e-05
I0923 00:55:38.455067 192876 solver.cpp:219] Iteration 8400 (0.3259 iter/s, 306.843s/100 iters), loss = 26.4586
I0923 00:55:38.455188 192876 solver.cpp:238] Train net output #0: accuracy = 0.546875
I0923 00:55:38.455196 192876 solver.cpp:238] Train net output #1: lambda = 8.5615
I0923 00:55:38.455205 192876 solver.cpp:238] Train net output #2: softmax_loss = 26.4586 (* 1 = 26.4586 loss)
I0923 00:55:38.455210 192876 sgd_solver.cpp:105] Iteration 8400, lr = 1e-05
I0923 01:00:39.942590 192876 solver.cpp:448] Snapshotting to binary proto file /home/unique/data-face/face_model/WT_sphereface27-40_iter_8500.caffemodel
I0923 01:00:42.497731 192876 sgd_solver.cpp:273] Snapshotting solver state to binary proto file /home/unique/data-face/face_model/WT_sphereface27-40_iter_8500.solverstate
I0923 01:00:45.680984 192876 solver.cpp:219] Iteration 8500 (0.325497 iter/s, 307.223s/100 iters), loss = 27.8068
I0923 01:00:45.681020 192876 solver.cpp:238] Train net output #0: accuracy = 0.578125
I0923 01:00:45.681025 192876 solver.cpp:238] Train net output #1: lambda = 8.54686
I0923 01:00:45.681032 192876 solver.cpp:238] Train net output #2: softmax_loss = 27.8068 (* 1 = 27.8068 loss)
I0923 01:00:45.681036 192876 sgd_solver.cpp:105] Iteration 8500, lr = 1e-05
I0923 01:05:52.483103 192876 solver.cpp:219] Iteration 8600 (0.325946 iter/s, 306.799s/100 iters), loss = 28.9902
I0923 01:05:52.483191 192876 solver.cpp:238] Train net output #0: accuracy = 0.574219
I0923 01:05:52.483199 192876 solver.cpp:238] Train net output #1: lambda = 8.53228
I0923 01:05:52.483207 192876 solver.cpp:238] Train net output #2: softmax_loss = 28.9902 (* 1 = 28.9902 loss)
I0923 01:05:52.483211 192876 sgd_solver.cpp:105] Iteration 8600, lr = 1e-05
I0923 01:10:59.224231 192876 solver.cpp:219] Iteration 8700 (0.326011 iter/s, 306.738s/100 iters), loss = 45.9285
I0923 01:10:59.224365 192876 solver.cpp:238] Train net output #0: accuracy = 0.429688
I0923 01:10:59.224373 192876 solver.cpp:238] Train net output #1: lambda = 8.51774
I0923 01:10:59.224380 192876 solver.cpp:238] Train net output #2: softmax_loss = 45.9285 (* 1 = 45.9285 loss)
I0923 01:10:59.224385 192876 sgd_solver.cpp:105] Iteration 8700, lr = 1e-05
I0923 01:16:05.965823 192876 solver.cpp:219] Iteration 8800 (0.326011 iter/s, 306.738s/100 iters), loss = 62.0409
I0923 01:16:05.965976 192876 solver.cpp:238] Train net output #0: accuracy = 0.289062
I0923 01:16:05.965996 192876 solver.cpp:238] Train net output #1: lambda = 8.50326
I0923 01:16:05.966014 192876 solver.cpp:238] Train net output #2: softmax_loss = 62.0409 (* 1 = 62.0409 loss)
I0923 01:16:05.966025 192876 sgd_solver.cpp:105] Iteration 8800, lr = 1e-05
I0923 01:21:12.843422 192876 solver.cpp:219] Iteration 8900 (0.325866 iter/s, 306.874s/100 iters), loss = 67.5738
I0923 01:21:12.843535 192876 solver.cpp:238] Train net output #0: accuracy = 0.222656
I0923 01:21:12.843542 192876 solver.cpp:238] Train net output #1: lambda = 8.48882
I0923 01:21:12.843550 192876 solver.cpp:238] Train net output #2: softmax_loss = 67.5738 (* 1 = 67.5738 loss)
I0923 01:21:12.843554 192876 sgd_solver.cpp:105] Iteration 8900, lr = 1e-05
I0923 01:26:14.555048 192876 solver.cpp:448] Snapshotting to binary proto file /home/unique/data-face/face_model/WT_sphereface27-40_iter_9000.caffemodel
I0923 01:26:17.105406 192876 sgd_solver.cpp:273] Snapshotting solver state to binary proto file /home/unique/data-face/face_model/WT_sphereface27-40_iter_9000.solverstate
I0923 01:26:20.287829 192876 solver.cpp:219] Iteration 9000 (0.325265 iter/s, 307.441s/100 iters), loss = 65.0543
I0923 01:26:20.287881 192876 solver.cpp:238] Train net output #0: accuracy = 0.238281
I0923 01:26:20.287886 192876 solver.cpp:238] Train net output #1: lambda = 8.47443
I0923 01:26:20.287894 192876 solver.cpp:238] Train net output #2: softmax_loss = 65.0543 (* 1 = 65.0543 loss)
I0923 01:26:20.287899 192876 sgd_solver.cpp:105] Iteration 9000, lr = 1e-05
I0923 01:31:27.157495 192876 solver.cpp:219] Iteration 9100 (0.325875 iter/s, 306.866s/100 iters), loss = 87.3365
I0923 01:31:27.157562 192876 solver.cpp:238] Train net output #0: accuracy = 0
I0923 01:31:27.157569 192876 solver.cpp:238] Train net output #1: lambda = 8.46009
I0923 01:31:27.157577 192876 solver.cpp:238] Train net output #2: softmax_loss = 87.3365 (* 1 = 87.3365 loss)

What should I do to solve the problem? Thanks!

关于video demo

在video demo 里 , 人脸框并不是正的,这是怎么实现的?MTCNN冰没有这个功能啊?

softmaxloss layer: num_output 10572

Since the WebFace contains 10,575 subjects, why using 10572?
Is that because mtcnn could only detect and align 10572 persons?

I'm using a face detection model and alignment method trained by myself.

less data

hi,proffesor, my data is much less than webface, how can i adjust superparameter to make the loss converge?

Training Cant't Converge.

Hi,I followed your instruction to train CASIA-WebFace dataset, but the training loss stays around 9.3 at the very beginning. Could you please give some possible advises to solve this problem? Here is part of my train log.
####train log
I0907 20:56:08.035786 10605 caffe.cpp:218] Using GPUs 0
I0907 20:56:08.148684 10605 caffe.cpp:223] GPU 0: Tesla P40
I0907 20:56:08.807466 10605 solver.cpp:44] Initializing solver from parameters:

base_lr: 0.01
display: 100
max_iter: 28000
lr_policy: "multistep"
gamma: 0.1
momentum: 0.9
weight_decay: 0.0005
snapshot: 1000
snapshot_prefix: "result/sphereface_model_maxpy_clean/ckpt0907_2"
solver_mode: GPU
device_id: 0
net: "code/sphereface_model_maxpy_clean.prototxt"
train_state {
level: 0
stage: ""
}
stepvalue: 16000
stepvalue: 24000
stepvalue: 28000
I0907 20:56:08.812855 10605 solver.cpp:87] Creating training net from net file: code/sphereface_model_maxpy_clean.prototxt
I0907 20:56:08.815649 10605 net.cpp:51] Initializing net from parameters:
name: "SpherefaceNet-20"
###skip the model part
I0907 20:56:11.030130 10605 solver.cpp:218] Iteration 0 (-1.9811e-31 iter/s, 0.203529s/100 iters), loss = 9.20592
I0907 20:56:11.030190 10605 solver.cpp:237] Train net output #0: lambda = 892.857
I0907 20:56:11.030210 10605 solver.cpp:237] Train net output #1: softmax_loss = 9.20592 (* 1 = 9.20592 loss)
I0907 20:56:11.030252 10605 sgd_solver.cpp:105] Iteration 0, lr = 0.01
I0907 20:56:11.079816 10605 blocking_queue.cpp:49] Waiting for data
I0907 20:57:30.478466 10605 solver.cpp:218] Iteration 100 (1.25873 iter/s, 79.4451s/100 iters), loss = 9.33074
I0907 20:57:30.478658 10605 solver.cpp:237] Train net output #0: lambda = 76.2195
I0907 20:57:30.478673 10605 solver.cpp:237] Train net output #1: softmax_loss = 9.33074 (* 1 = 9.33074 loss)
I0907 20:57:30.478684 10605 sgd_solver.cpp:105] Iteration 100, lr = 0.01
I0907 20:58:46.554661 10605 solver.cpp:218] Iteration 200 (1.31453 iter/s, 76.073s/100 iters), loss = 9.30099
I0907 20:58:46.554803 10605 solver.cpp:237] Train net output #0: lambda = 39.8089
I0907 20:58:46.554821 10605 solver.cpp:237] Train net output #1: softmax_loss = 9.30099 (* 1 = 9.30099 loss)
I0907 20:58:46.554834 10605 sgd_solver.cpp:105] Iteration 200, lr = 0.01
I0907 21:00:32.839994 10605 solver.cpp:218] Iteration 300 (0.940902 iter/s, 106.281s/100 iters), loss = 9.41046
I0907 21:00:32.840147 10605 solver.cpp:237] Train net output #0: lambda = 26.9397
I0907 21:00:32.840165 10605 solver.cpp:237] Train net output #1: softmax_loss = 9.41046 (* 1 = 9.41046 loss)
I0907 21:00:32.840178 10605 sgd_solver.cpp:105] Iteration 300, lr = 0.01
I0907 21:02:01.073664 10605 solver.cpp:218] Iteration 400 (1.1334 iter/s, 88.23s/100 iters), loss = 9.35314
I0907 21:02:01.073825 10605 solver.cpp:237] Train net output #0: lambda = 20.3583
I0907 21:02:01.073848 10605 solver.cpp:237] Train net output #1: softmax_loss = 9.35314 (* 1 = 9.35314 loss)
I0907 21:02:01.073860 10605 sgd_solver.cpp:105] Iteration 400, lr = 0.01
I0907 21:03:35.687438 10605 solver.cpp:218] Iteration 500 (1.05697 iter/s, 94.6099s/100 iters), loss = 9.42017
I0907 21:03:35.687583 10605 solver.cpp:237] Train net output #0: lambda = 16.3613
I0907 21:03:35.687602 10605 solver.cpp:237] Train net output #1: softmax_loss = 9.42017 (* 1 = 9.42017 loss)
I0907 21:03:35.687613 10605 sgd_solver.cpp:105] Iteration 500, lr = 0.01
I0907 21:05:06.772781 10605 solver.cpp:218] Iteration 600 (1.09792 iter/s, 91.0816s/100 iters), loss = 9.3796
I0907 21:05:06.772953 10605 solver.cpp:237] Train net output #0: lambda = 13.6761
I0907 21:05:06.772974 10605 solver.cpp:237] Train net output #1: softmax_loss = 9.3796 (* 1 = 9.3796 loss)
I0907 21:05:06.772987 10605 sgd_solver.cpp:105] Iteration 600, lr = 0.01
I0907 21:06:23.862064 10605 solver.cpp:218] Iteration 700 (1.29725 iter/s, 77.086s/100 iters), loss = 9.37048
I0907 21:06:23.862254 10605 solver.cpp:237] Train net output #0: lambda = 11.7481
I0907 21:06:23.862272 10605 solver.cpp:237] Train net output #1: softmax_loss = 9.37048 (* 1 = 9.37048 loss)
P.S I've read the issue #14 and issue #7 , but neither provides feasible solutions. Could you please provide your solver settings and the lambda related parameters(lambda min, base and
gamma) for trainning? Thx a lot.

Not achieving good result on MegaFace

First of all, thank you for providing the Sphereface training code for us.

I have retrained your model following your instruction. However, I only got 67.35% on Rank-1 Identification Accuracy on Megaface testing, while you got 72.73%. We used your code and trained from scratch.

Training with Softmax + CenterLoss rendered the correct result as reported in your paper, i.e. ~65%.

I believe this is the same protocol you used for Megaface Testing, right? If not, could you kindly point out the difference? Thank you very much!

issue of a-softmax loss

Hi,
I set the random_seed in solver.prototxt, use the same CNN architecture and the same training set for evaluating the repeatability.
In softmax loss or softmax with centre loss, I can get the same softmax loss and same center loss in every iteration during training, but it is not the case in a-softmax (sphereface). In a-softmax, the first iteration is same, but it becomes difference when I repeat to train the model from scratch.
Would you like to explain it?

question about formula derivation

Hi, @wy1iu, sphereface is quite a great work and i have some questions about the formula derivation in margin_inner_product_layer. Such as in "margin_inner_product_layer.hpp" file, why set "sign_0 = sign(cos_theta)", "sign_1 = sign(abs(cos_theta) - 0.5)", "sign_2 = sign_0 * (1 + sign_1) - 2", "sign_3 = sign_0 * sign(2 * cos_theta_quadratic_ - 1)", "sign_4 = 2 * sign_0 + sign_3 - 3".
If i want get a pent type, what variables "sign_5" should i set.

About BatchNorm and dropout

As I seen in your prototxt file, you didn't use neither batchnorm layer nor dropout. Why?
Does such layers affect the network converging?
Thanks in advance.

caffe-face features

Hi --

This is a question better directed at the https://github.com/ydwen/caffe-face issues, but issues are disabled and that project was written by some of the same authors.

The LFW features are available for download on the caffe-face projects page -- is there evaluation code available to reproduce the 99% accuracy reported in the paper? The paper mentions using PCA on the features, but I haven't been able to get that kind of accuracy using the pretrained vectors. Any ideas?

Thanks

Issue with largemargin_inner_product_layer.cpp with new caffe version

Hello,

I tried to run the latest caffe version with largemargin layer however I get an error in the largemargin_inner_product_layer.hpp where it says the the Layer does take 2 arguments and not one (Ftype and Btype). Could you please update the code in the largemargin layer.

Thank you very much,
Best

how to set theta range in [0,pi/m]

I check the code, I think it can not ensure the theta in [0,pi/m]. if the theta is not in the [0,pi/m], I think it will be some wrong.

about video demo

hello,my tutor asks me to use caffemodel to make a video demo,can you tell me how to do ,
thanks

Network prototxt in SphereFace

Hi, @wy1iu @ydwen

Thank you for sharing the code. I have trained a model using 28layer (as the center face) with A-softmax, which works well. However, I have struggled training with the 64layer structure you mentioned in the original paper for several days. Could you please kindly release one of you network architectures in the paper (either 20layer or 36layer or 64layer) so I can compare the difference between the prototxt I wrote from yours.

BTW, it seems there is no pooling layer in your architecture, right? Just using convolution layer of stride 2 instead of pooling?

Thanks in advance!

Issue about training the model

Hey, I trained the model as you mentioned in the README using the same ide and face datebase. But the loss increased from 7 to 87 after 10k iterations. Could you tell me how to analyse and solve this problem.

Common Resnet gives bad result.

Hi authors, I have tried your network structure with sphere loss and it can give similar result which mentioned in your paper. However, when I switched to use common resnet-50 or resnet-101 I can just got LFW score at about 97.xx%. Did you ever tried any other network structures?

I thought that the problem was caused by small norm(fx) where fx is the 512-dim embedding. As the W is normalized to one in sphereface, fx*W will become very small if norm(fx) is small to affect the total loss value.
According to this I tried two approaches:

  1. Normalize fx to a larger value like 32,
  2. Use Prelu everywhere and set wd of the bias var in last FC layer to 0 and also remove the last BN layer.

Neither of them can work.
Do you have any idea or give some hints?

How to set the solver parameter?

Since I only have 2*1080Ti, using batch_size=256 will out of mermory.
I set batch_size=64, so how to set the stepvalue,
stepvalue: 16000*4
stepvalue: 24000*4
stepvalue: 28000*4
max_iter: 28000*4
other parameters are same as the solver providied by this repository .
is it ok?
And if I use Relu instead of PRelu, is it just affecting the coverage time. How about the precision?

train on large dataset

have you train your a-softmax on a much more dataset for example msceleb1m.
I trained a-softmax on a 10m dataset, abount 200k identities, the loss did not converge,
but softmax or center loss done well.

how to get the face embedding

Is there any pretrained model using this sphereface concept? If so how do i get the face embeddings of a custom image using that pre trained model?

Verifying the release caffemodel in the result of Megaface

Hi,
I have just evaluated your 20-layer CNN architecture caffemodel in Megaface.
The results are below:
Rank-1 Identification Accuracy with 1 Million Distractors, Set1 (FaceScrub )
77.6892% (75.766% is their 68 layers published in the official homepage of Megaface )
Rank-1 Identification Accuracy with 1 Million Distractors, Set1, (testing age-invariant recognition at scale, FGNet)
23.5023% (47.555% is their 68 layers published in the official homepage of Megaface )

Is it right? did any other guys evaluate it as well?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.