Механизм приложения Google с интерфейсом ClientLogin для Objective C

Прежде чем перейти к решению, которое я собираюсь предоставить, я сначала прокомментирую предлагаемое решение вопросов. Первое решение будет работать лучше, чем второе. Это потому, что очень трудно интерпретировать (вероятность) значения выходных данных нейронной сети. Близость значений может быть вызвана сходством участвующих классов (в этом случае собака может выглядеть как кошка). Иногда вы можете получить невидимые классы, назначенные на один из классов с высокой вероятностью.

Большинство контролируемых алгоритмов машинного обучения классификации предназначены для отображения входных данных в одном из некоторого фиксированного числа классов. Этот тип классификации называется классификация замкнутого мира .
Например.

  • MNIST - классификация рукописных цифр
  • Классификация кошек и собак

Когда в классификации участвуют некоторые немаркированные / неизвестные классы, подход называется классификацией открытого мира. Опубликованы различные работы [ 1 , 2 , 3 ].

Я объясню свое решение, используя решение, предложенное в 3 . Существует два варианта применения классификации открытого мира (здесь я буду ссылаться на OWC) к рассматриваемой проблеме.

  1. Классификация всех новых классов как одного класса
  2. Классификация всех новых классов как одного класса, затем дальнейшая группировка похожих выборок в один класс и различные выборки в разные классы.

1. Классификация всех новых классов как одного класса

Хотя может быть много типов моделей, которые могли бы соответствовать этому типу классификации (Одним из может быть первое решение, предложенное вопросом.) Я бы обсудил модель [119 ] 3 . Здесь сеть сначала решает классифицировать или отклонить ввод. В идеале, если образец взят из видимых классов, тогда сеть будет классифицироваться как один из видимых классов. В противном случае сеть отклоняет. Авторы 3 назвали эту сеть открытой классификационной сетью (OCN). Реализация OCN в Keras могла бы быть такой (я упростил сеть, чтобы сосредоточиться только на выводе модели.

inputs = keras.layers.Input(shape=(28, 28,1))
x = keras.layers.Conv2D(64, 3, activation="relu")(inputs)
x = keras.layers.Flatten()(x)

embedding = keras.layers.Dense(256, activation="linear", name="embedding_layer")(x)
reject_output = keras.layers.Dense(1, activaton="sigmoid", name="reject_layer")(embedding)

classification_output = keras.layers.Dense(num_of_classes, activaton="softmax", name="reject_layer")(embedding)

ocn_model = keras.models.Model(inputs=inputs, outputs=[reject_output, classification_output)

Модель обучена таким образом, что совместно оптимизирует потери reject_output и classification_output .

2. Классификация всех новых классов как одного класса, затем дальнейшая группировка аналогичных

Авторы 3 использовали другую сеть для поиска сходства между выборками. Они назвали сеть Парная классификационная сеть (PCN). PCN классифицирует, являются ли два входа из одного и того же класса или разных классов. Мы можем использовать embedding первого решения и использовать попарные метрики подобия для создания сети PCN. В PCN веса делятся для обоих Это может быть реализовано с использованием keras

embedding_model = keras.layers.Sequential([
    keras.layers.Conv2D(64, 3, activation="relu", input_shape=(28, 28,1))
    keras.layers.Flatten(),
    embedding = keras.layers.Dense(256, activation="linear", name="embedding_layer")
])

input1 = keras.layers.Input(shape=(28, 28, 1))
input2 = keras.layers.Input(shape=(28, 28, 1))

embedding1 = embedding_model(input1)
embedding2 = embedding_model(input2)

merged = keras.layers.Concatenate()([embedding1, embedding2])
output = keras.layers.Dense(1, activation="sigmoid")(merged)

pcn_model = keras.models.Model(inputs=[input1, input2], outputs=output)

Модель PCN будет обучена уменьшать расстояние от одного и того же и увеличивать расстояние между различными классами.

После обучения сети PCN автоматически -encoder обучен изучению полезных представлений от невидимых классов. Алгоритм используется для группировки (кластеризации) невидимых классов с использованием модели PCN в качестве функции расстояния.

10
задан Community 23 May 2017 в 12:19
поделиться

7 ответов

Добавление примера кода к этому вопросу, потому что кто-то связался со мной непосредственно о моем решении. Обратите внимание, что необходимо установить "сервисный" параметр, равный "ах" по начальному маркерному запросу.

Начальный Запрос Маркера [сделанный синхронно] ПРИМЕЧАНИЕ: "сервисный" параметр устанавливается на "ах", и "источник" просто установлен на "myapp", необходимо использовать название приложения.

//create request
NSString* content = [NSString stringWithFormat:@"accountType=HOSTED_OR_GOOGLE&Email=%@&Passwd=%@&service=ah&source=myapp", [loginView username].text, [loginView password].text];
NSURL* authUrl = [NSURL URLWithString:@"https://www.google.com/accounts/ClientLogin"];
NSMutableURLRequest* authRequest = [[NSMutableURLRequest alloc] initWithURL:authUrl];
[authRequest setHTTPMethod:@"POST"];
[authRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"];
[authRequest setHTTPBody:[content dataUsingEncoding:NSASCIIStringEncoding]];

NSHTTPURLResponse* authResponse;
NSError* authError;
NSData * authData = [NSURLConnection sendSynchronousRequest:authRequest returningResponse:&authResponse error:&authError];  

NSString *authResponseBody = [[NSString alloc] initWithData:authData encoding:NSASCIIStringEncoding];

//loop through response body which is key=value pairs, seperated by \n. The code below is not optimal and certainly error prone. 
NSArray *lines = [authResponseBody componentsSeparatedByString:@"\n"];
NSMutableDictionary* token = [NSMutableDictionary dictionary];
for (NSString* s in lines) {
    NSArray* kvpair = [s componentsSeparatedByString:@"="];
    if ([kvpair count]>1)
        [token setObject:[kvpair objectAtIndex:1] forKey:[kvpair objectAtIndex:0]];
}

//if google returned an error in the body [google returns Error=Bad Authentication in the body. which is weird, not sure if they use status codes]
if ([token objectForKey:@"Error"]) {
    //handle error
};

Следующий шаг должен заставить Вашу работу приложения механизма приложения Google давать Вам cookie ASCID. Я не уверен, почему существует этот дополнительный шаг, это, кажется, проблема о конце Google и вероятно почему GAE в настоящее время не находится в их перечисленной obj-c библиотеке API данных Google. Мои тесты показывают, что я должен запросить cookie в синхронизации порядка с GAE. Кроме того, заметьте, что я ничего не делаю с cookie. Это кажется только путем запроса этого и получение cookied, будущие запросы будут автоматически содержать cookie. Я не уверен, является ли это вещью iPhone до н.э, мое приложение является приложением для iPhone, но я не полностью понимаю то, что происходит с этим cookie.Примечание: использование "myapp.appspot.com".

NSURL* cookieUrl = [NSURL URLWithString:[NSString stringWithFormat:@"http://myapp.appspot.com/_ah/login?continue=http://myapp.appspot.com/&auth=%@", [token objectForKey:@"Auth"]]];
    NSLog([cookieUrl description]);
    NSHTTPURLResponse* cookieResponse;
    NSError* cookieError;
    NSMutableURLRequest *cookieRequest = [[NSMutableURLRequest alloc] initWithURL:cookieUrl];

    [cookieRequest setHTTPMethod:@"GET"];

    NSData* cookieData = [NSURLConnection sendSynchronousRequest:cookieRequest returningResponse:&cookieResponse error:&cookieError];   

Наконец, я могу отправить json на свое gae приложение.Примечание: отрывок ниже является асинхронным запросом. Мы можем обработать ответы путем реализации didReceiveResponse, didReceiveData, didFailWIthError.

NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://myapp.appspot.com/addRun?auth=%@", mytoken]];
    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:@"my http body";

    NSURLConnection *connectionResponse = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (!connectionResponse) {
        NSLog(@"Failed to submit request");
    } else {
        NSLog(@"Request submitted");
    }
16
ответ дан 3 December 2019 в 20:06
поделиться

Проверьте код, который делает это в официальном SDK. Последний выпуск SDK даже имеет его разделение в его собственный файл.

1
ответ дан 3 December 2019 в 20:06
поделиться

1-й - благодарит за большое сообщение, это действительно запустило меня.

2-й - я ударял его со своим приложением, пробуя к POST к GAE, в то время как аутентифицируется.

Это - запрос, создается при РЕГИСТРАЦИИ, после того как Вы получили authtoken:

    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];


[request setURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"image/png" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];

[request setValue:authtoken forHTTPHeaderField:@"auth"];  // <-- the magic
  • mattb
1
ответ дан 3 December 2019 в 20:06
поделиться

Обратите внимание, что Google недавно изменил способ индикации сбоев авторизации. Раньше они помещали в ответ жетон ошибки. Теперь они просто возвращают статус 403 (Запрещено). Это нарушило мой код!

0
ответ дан 3 December 2019 в 20:06
поделиться

Спасибо за этот пост и особенно за ответ Кита, но это не работает для меня. Даже если для меня это кажется нормальным... очень странно.

Я проверил этот пост (How do you access an authenticated Google App Engine service from a (non-web) python client?), где говорится о том, как сделать то же самое в python. Я протестировал его, и он работает.

И код на языке objective C, предложенный Китом, действительно похож на код на python.

Но когда я пытаюсь получить токен "Auth", authData содержит Error=BadAuthentication.

У кого-нибудь есть идеи о возможных проблемах?

0
ответ дан 3 December 2019 в 20:06
поделиться

Использование HOSTED_OR_GOOGLE неправильно, и я объясню почему.

В мире Google существует два вида учетных записей. Те, которые вы создаете для GMail и т.д., являются учетными записями "Google". Те, которые вы создаете для Apps for Domains, - это "Hosted" аккаунты. Вы можете использовать электронную почту размещенного аккаунта для создания аккаунта Google, создав таким образом адрес электронной почты, связанный с обоими типами аккаунтов.

Ваше приложение Google App Engine может быть настроено для работы с (1) аккаунтами Google или (2) размещенными аккаунтами для определенного домена.

Предположим, что мы разрабатываем приложение для аккаунтов Google. Пользователь вводит адрес электронной почты, который связан с аккаунтом Google и аккаунтом Hosted. Google будет использовать аккаунт Google для входа в систему. Все работает отлично.

Теперь, если мы используем ClientLogin с этим же адресом электронной почты и используем HOSTED_OR_GOOGLE для типа учетной записи, вход будет успешным, но будет использоваться учетная запись Hosted, поскольку учетная запись Hosted имеет приоритет. Как я уже говорил выше, вы не можете использовать Hosted Account для приложения, которое ожидает аккаунт Google. Поэтому аутентификация не будет работать.

Итак, при использовании ClientLogin для аутентификации в приложении Google App Engine необходимо использовать GOOGLE для типа аккаунта, если приложение предназначено для аккаунтов Google, или HOSTED для типа аккаунта, если приложение предназначено для домена.

0
ответ дан 3 December 2019 в 20:06
поделиться

Я создал несколько классов obj-c для реализации ClientLogin, включая поддержку Google App Engine:

http://github.com/cameronr/GoogleAppEngineAuth

1
ответ дан 3 December 2019 в 20:06
поделиться