<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Cole Murray on Medium]]></title>
        <description><![CDATA[Stories by Cole Murray on Medium]]></description>
        <link>https://medium.com/@colemurray?source=rss-8d62c20970c7------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*Oc2bhM97XeQSwt1KfM8hLA.jpeg</url>
            <title>Stories by Cole Murray on Medium</title>
            <link>https://medium.com/@colemurray?source=rss-8d62c20970c7------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 12 Nov 2026 08:19:26 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@colemurray/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Building RAG Pipelines on AWS: A Practical Guide to Bedrock + Pinecone]]></title>
            <link>https://colemurray.medium.com/building-rag-pipelines-on-aws-a-practical-guide-to-bedrock-pinecone-4d815de4d35a?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/4d815de4d35a</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[retrieval-augmented-gen]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Thu, 12 Jun 2025 20:52:31 GMT</pubDate>
            <atom:updated>2025-06-12T20:52:31.479Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mjjX8p23TCfpd3b-Id2c8g.png" /><figcaption>Build your AWS RAG pipeline</figcaption></figure><p>Most teams spend weeks wrestling with RAG infrastructure before they can answer their first question. I built this open-source AWS RAG application to cut that timeline from weeks to hours — giving you a solid foundation that demonstrates enterprise-grade patterns and scales from proof-of-concept to production deployment.</p><h3>The RAG Infrastructure Problem</h3><p>Here’s what I see repeatedly: engineering teams get excited about Retrieval-Augmented Generation, spin up a quick prototype with OpenAI embeddings and a local vector database, then hit a wall when they need to ship something that handles real traffic, integrates with existing AWS infrastructure, and meets enterprise security requirements.</p><p>The gap between “RAG demo” and “RAG in production” is massive. You need:</p><ul><li><strong>Managed embedding models</strong> that don’t require ML infrastructure</li><li><strong>Enterprise vector databases</strong> with proper access controls and monitoring</li><li><strong>Scalable ingestion pipelines</strong> that handle thousands of documents</li><li><strong>Production APIs</strong> with error handling, logging, and health checks</li><li><strong>Cost-efficient architecture</strong> that doesn’t break the budget during experimentation</li></ul><p>That’s exactly what this AWS RAG application delivers.</p><h3>How This Open-Source RAG Pipeline Works</h3><p>I designed this implementation around two core principles: use managed services wherever possible and optimize for developer velocity. The result is a RAG pipeline that leverages AWS Bedrock and Pinecone to eliminate infrastructure complexity while demonstrating enterprise-grade patterns.</p><h3>The Technical Stack</h3><p><strong>AWS Bedrock Integration:</strong></p><ul><li><strong>Titan Text Embeddings V2</strong> for 1024-dimensional vectors with superior retrieval performance</li><li><strong>Claude Sonnet 4</strong> for response generation with built-in safety guardrails</li><li><strong>Native AWS IAM integration</strong> for enterprise security and compliance</li><li><strong>Pay-per-use pricing</strong> that scales from $10/month POCs to enterprise workloads</li></ul><p><strong>Pinecone Vector Database:</strong></p><ul><li>Serverless vector search with sub-second query latency</li><li>Metadata filtering for source attribution and access control</li><li>Automatic scaling that handles traffic spikes without configuration</li><li>Free starter tier perfect for development and testing</li></ul><p><strong>FastAPI Application with Enterprise Patterns:</strong></p><pre>@app.post(&quot;/query&quot;, response_model=QueryResponse)<br>async def query_documents(request: QueryRequest, service: RAGService = Depends(get_rag_service)):<br>    &quot;&quot;&quot;Process RAG queries with comprehensive error handling and monitoring.&quot;&quot;&quot;<br>    start_time = time.time()<br>    <br>    # Generate query embedding using Bedrock Titan<br>    query_embedding = await service.generate_embedding(request.query)<br>    <br>    # Search similar chunks in Pinecone<br>    matches = await service.search_similar_chunks(<br>        query_embedding, <br>        request.max_chunks or settings.top_k,<br>        request.similarity_threshold or settings.similarity_threshold<br>    )<br>    <br>    # Generate response using Claude Sonnet 4<br>    response = await service.generate_response(request.query, matches)<br>    <br>    processing_time = (time.time() - start_time) * 1000<br>    return QueryResponse(<br>        answer=response,<br>        query=request.query,<br>        sources=matches,<br>        processing_time_ms=processing_time<br>    )</pre><h3>What You Get Out of the Box</h3><p>Complete Document Ingestion Pipeline:</p><ul><li>Support for local files and S3 buckets</li><li>Intelligent text chunking with LangChain text splitters</li><li>Batch processing for efficient embedding generation</li><li>Comprehensive error handling and retry logic</li></ul><p>FastAPI Server with Best Practices:</p><ul><li>Async request handling for high concurrency</li><li>Pydantic validation for type safety</li><li>Structured logging with contextual information</li><li>Health checks for all external dependencies</li><li>CORS middleware for web application integration</li></ul><p>Developer Experience Tools:</p><ul><li>Interactive setup wizard that validates your environment</li><li>Comprehensive test suite for API validation</li><li>Docker containerization for consistent deployments</li><li>Sample documents for immediate experimentation</li></ul><p>Enterprise-Grade Patterns:</p><ul><li>IAM-based access control through AWS Bedrock</li><li>Secrets management best practices</li><li>Cost monitoring and optimization guidance</li><li>Scalable deployment options (Lambda, ECS, Kubernetes)</li></ul><h3>Performance Characteristics</h3><p>I optimized this implementation for real-world usage patterns:</p><ul><li>Query latency: Sub-2-second response times for most queries</li><li>Concurrent users: Handles 50+ simultaneous requests</li><li>Document processing: 1000+ documents per hour ingestion rate</li><li>Cost efficiency: Linear scaling with predictable pricing</li></ul><p>The vector database uses cosine similarity with 1024-dimensional Titan embeddings, providing superior retrieval accuracy compared to smaller embedding models. Claude Sonnet 4 generates responses with built-in citation capabilities, ensuring transparency in source attribution.</p><h3>Getting Started: From Zero to RAG in 30 Minutes</h3><p>The fastest path to a working RAG pipeline:</p><pre># Clone and setup<br>git clone https://github.com/ColeMurray/aws-rag-application.git<br>cd aws-rag-application<br>pip install -r requirements.txt<br> <br># Interactive configuration<br>python scripts/quickstart.py<br> <br># Ingest sample documents<br>python src/ingest.py --source-type local --path ./data<br> <br># Start the API server<br>python src/app.py\</pre><p>The quickstart script handles environment validation, AWS credential verification, and service connectivity testing. Within minutes, you’ll have a working RAG API that can answer questions about your documents.</p><p>For production deployment, the included Docker configuration supports both local development and cloud deployment:</p><pre># Local development with hot reload<br>docker-compose up --build<br> <br># Production deployment<br>docker build -t rag-pipeline .<br>docker run -p 8000:8000 rag-pipeline</pre><h3>Why This Matters for Your Team</h3><p>This isn’t just another RAG tutorial;it’s a demonstration of how we approach RAG implementations in our consulting practice. The application showcases modern best practices that we apply when building production systems for clients:</p><ul><li>Type-safe configuration with Pydantic prevents runtime errors</li><li>Structured logging provides observability for production debugging</li><li>Comprehensive error handling ensures graceful degradation</li><li>Security-first design follows AWS IAM best practices</li><li>Cost optimization leverages managed services to minimize operational overhead</li></ul><p>Whether you’re building internal knowledge bases, customer support automation, or document analysis tools, this RAG pipeline demonstrates the architectural patterns and best practices that scale with your requirements.</p><p>The complete implementation, documentation, and deployment guides are available on <a href="https://github.com/ColeMurray/aws-rag-application">GitHub</a>. Start with the sample documents, then point the ingestion pipeline at your own data sources — S3 buckets, document repositories, or any text-based content.</p><p>Ready to build your RAG pipeline?</p><p>The code demonstrates proven patterns, the documentation is comprehensive, and the architecture showcases how to scale from prototype to enterprise. Clone the repository and start experimenting with your first intelligent document system this week.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4d815de4d35a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Generating Synthetic Data With LLMs For Fine-tuning]]></title>
            <link>https://colemurray.medium.com/generating-synthetic-data-with-llms-for-fine-tuning-7d93bf271794?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/7d93bf271794</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Tue, 30 Jul 2024 16:59:33 GMT</pubDate>
            <atom:updated>2024-08-01T00:43:53.607Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*STkMvWpjxyoQJ0iT" /><figcaption>Generating synthetic data with llms for fine-tuning</figcaption></figure><p>Generating synthetic data with LLMs can remove the need to manually collect, annotate and review large datasets and be used to fine-tune smaller language models for machine local inference.</p><p>Imagine staring down an 80TB compressed dataset. That’s exactly where I found myself when I decided to explore the <a href="https://commoncrawl.org/">Common Crawl dataset</a>. My first task? To classify the intent of each webpage. Simple enough in theory, but when you’re dealing with a dataset that makes most hard drives weep, the challenges stack up fast.</p><h4>The Common Crawl Conundrum</h4><p>For those unfamiliar, Common Crawl is a nonprofit that creates and maintains an open repository of web crawl data that can be accessed and analyzed by anyone. It’s a goldmine of information, but it’s also a behemoth that demands respect — and a solid game plan.</p><p>Calling OpenAI or Anthropic was not viable as it is slow and costly.</p><p>The challenges:<br>- 80TB+ of compressed data to process<br>- Significant latency for each API call<br>- Costs that would make even the most generous budget blush<br>- Rate limits</p><p>I needed a solution that was fast, cost-effective, and could scale to handle the enormity of Common Crawl. What if I could create a model that had the smarts of GPT-4 but could run locally at lightning speed?</p><h4>The Lightbulb Moment: BERT Meets GPT-4</h4><p>I decided to combine the power of GPT-4o for generating high-quality synthetic data with the efficiency of a fine-tuned BERT model.</p><p>The plan was simple:<br>1. Use GPT-4 to generate a diverse, high-quality dataset of synthetic web pages<br>2. Fine-tune a BERT model on this synthetic data<br>3. Deploy the fine-tuned model to classify the Common Crawl dataset locally</p><p>This approach offered several advantages:<br>- No need for API calls during classification, drastically reducing latency<br>- A one-time cost for data generation and training, rather than per-page API fees<br>- The ability to process the entire dataset on local hardware, solving scalability issues</p><p>In this tutorial, I’m going to walk you through this process step by step. Whether you’re grappling with your own massive dataset or just curious about pushing the boundaries of what’s possible with AI and big data, this guide is for you.</p><p>Let’s get started!</p><h4>The Solution: GPT-4 Meets BERT</h4><p>By leveraging the latest advancements in GPT-4, we can generate synthetic HTML data that’s not only realistic but also diverse. This approach allows us to create a custom model for classifying web pages without the need for a large, manually labeled dataset. Let me walk you through the process I’ve developed.</p><h4>Step 1: Generating Synthetic HTML Data with GPT-4o</h4><p>First things first, let’s set up our environment. You’ll need to install the OpenAI library:</p><pre>pip install openai</pre><p>We’re going to use GPT-4 to generate our synthetic HTML data.</p><pre>import random<br>import json<br>import os<br>import logging<br>from openai import OpenAI<br>from datetime import datetime<br><br># Set up logging<br>logging.basicConfig(level=logging.INFO, format=&#39;%(asctime)s - %(levelname)s - %(message)s&#39;)<br><br># Add your key to env vars<br>client = OpenAI(api_key=os.environ[&#39;OPENAI_API_KEY&#39;])<br><br>def generate_synthetic_html(page_type):<br>    prompt = f&quot;&quot;&quot;<br>    Generate an HTML page for a {page_type} website. Make it realistic and diverse.<br>    Include appropriate tags, headings, and content based on the page type.<br>    For an informational page, include a main question and its answer.<br>    For a navigational page, include a navigation menu and some basic content.<br>    For a commercial page, include product information and a call-to-action.<br>    For a transactional page, include a form or a clear action for the user to take.<br>    Return the result as a JSON object with two keys: &#39;html&#39; for the HTML content, and &#39;summary&#39; for a brief description of the page.<br>    &quot;&quot;&quot;<br>    logging.info(f&quot;Generating synthetic HTML for {page_type} page&quot;)<br>    response = client.chat.completions.create(<br>        model=&quot;gpt-4o&quot;,<br>        messages=[<br>            {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: &quot;You are a web developer creating diverse and realistic HTML pages.&quot;},<br>            {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: prompt}<br>        ],<br>        max_tokens=3000,<br>        n=1,<br>        response_format={ &quot;type&quot;: &quot;json_object&quot; },<br>        stop=None,<br>        temperature=0.8<br>    )<br>    content = response.choices[0].message.content<br>    logging.info(content)<br>    return json.loads(response.choices[0].message.content)<br><br>def generate_dataset(num_samples):<br>    page_types = [&quot;informational&quot;, &quot;navigational&quot;, &quot;commercial&quot;, &quot;transactional&quot;]<br>    dataset = []<br>    for i in range(num_samples):<br>        page_type = random.choice(page_types)<br>        logging.info(f&quot;Generating sample {i+1}/{num_samples}&quot;)<br>        result = generate_synthetic_html(page_type)<br>        dataset.append((result[&#39;html&#39;], page_type, result[&#39;summary&#39;]))<br>    return dataset<br><br>def write_dataset_to_file(dataset, filename):<br>    logging.info(f&quot;Writing dataset to file: {filename}&quot;)<br>    with open(filename, &#39;w&#39;, encoding=&#39;utf-8&#39;) as f:<br>        json.dump(dataset, f, ensure_ascii=False, indent=2)<br>    logging.info(f&quot;Dataset successfully written to {filename}&quot;)<br><br>def main():<br>    num_samples = 10  # Replace with your desired count<br>    logging.info(f&quot;Starting synthetic data generation for {num_samples} samples&quot;)<br>    <br>    dataset = generate_dataset(num_samples)<br>    <br>    # Create a timestamp for the filename<br>    timestamp = datetime.now().strftime(&quot;%Y%m%d_%H%M%S&quot;)<br>    filename = f&quot;synthetic_dataset_{timestamp}.json&quot;<br>    <br>    write_dataset_to_file(dataset, filename)<br>    <br>    logging.info(&quot;Synthetic data generation complete&quot;)<br><br>if __name__ == &quot;__main__&quot;:<br>    main()</pre><p>This script uses GPT-4 to create HTML content based on different page types, giving us a rich, diverse dataset to work with.</p><h4>Step 2: Preparing the Data for BERT</h4><p>Now that we have our synthetic data, it’s time to prepare it for BERT. Here’s where the magic happens:</p><pre>pip install transformers[torch] torch datasets</pre><pre>import torch<br>from transformers import BertTokenizer, BertForSequenceClassification, Trainer, TrainingArguments<br>from datasets import Dataset<br>import json<br>import glob<br>import os<br><br># Load the most recent dataset<br>def load_most_recent_dataset():<br>    list_of_files = glob.glob(&#39;synthetic_dataset_*.json&#39;)<br>    if not list_of_files:<br>        raise FileNotFoundError(&quot;No synthetic dataset files found.&quot;)<br>    latest_file = max(list_of_files, key=os.path.getctime)<br>    with open(latest_file, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f:<br>        return json.load(f)<br><br># Load the dataset<br>dataset = load_most_recent_dataset()<br><br># Unpack our dataset<br>html_texts, labels, summaries = zip(*dataset)<br>label_map = {&quot;informational&quot;: 0, &quot;navigational&quot;: 1, &quot;commercial&quot;: 2, &quot;transactional&quot;: 3}<br>encoded_labels = [label_map[label] for label in labels]<br><br># Create a Hugging Face Dataset<br>hf_dataset = Dataset.from_dict({<br>    &quot;text&quot;: html_texts,<br>    &quot;summary&quot;: summaries,<br>    &quot;label&quot;: encoded_labels<br>})<br><br># Now, let&#39;s tokenize our data<br>tokenizer = BertTokenizer.from_pretrained(&#39;bert-base-uncased&#39;)<br><br>def tokenize_function(examples):<br>    combined_text = [f&quot;{html}\n\nSummary: {summary}&quot; for html, summary in zip(examples[&quot;text&quot;], examples[&quot;summary&quot;])]<br>    tokenized = tokenizer(combined_text, padding=&quot;max_length&quot;, truncation=True, max_length=1024)<br>    tokenized[&quot;labels&quot;] = examples[&quot;label&quot;]<br>    return tokenized<br><br>tokenized_dataset = hf_dataset.map(tokenize_function, batched=True, remove_columns=hf_dataset.column_names)<br><br># Split into training and validation sets<br>train_val_dataset = tokenized_dataset.train_test_split(test_size=0.2)<br>train_dataset = train_val_dataset[&quot;train&quot;]<br>val_dataset = train_val_dataset[&quot;test&quot;]</pre><h4>Step 3: Fine-tuning BERT</h4><p>Here’s where it all comes together. We’re going to fine-tune BERT on our synthetic dataset:</p><pre># Load pre-trained BERT model<br>model = BertForSequenceClassification.from_pretrained(&#39;bert-base-uncased&#39;, num_labels=4)<br><br># Set up training arguments<br>training_args = TrainingArguments(<br>    output_dir=&quot;./results&quot;,<br>    num_train_epochs=3,<br>    per_device_train_batch_size=8,<br>    per_device_eval_batch_size=8,<br>    warmup_steps=500,<br>    weight_decay=0.01,<br>    logging_dir=&quot;./logs&quot;,<br>    logging_steps=10,<br>    evaluation_strategy=&quot;epoch&quot;,<br>    save_strategy=&quot;epoch&quot;,<br>    load_best_model_at_end=True,<br>    remove_unused_columns=False,<br>)<br><br>from transformers import DataCollatorWithPadding<br><br>data_collator = DataCollatorWithPadding(tokenizer=tokenizer)<br><br># Create Trainer instance<br>trainer = Trainer(<br> model=model,<br> args=training_args,<br> train_dataset=train_dataset,<br> eval_dataset=val_dataset,<br> data_collator=data_collator<br>)<br><br># Fine-tune the model<br>trainer.train()<br><br># Save our fine-tuned model<br>model.save_pretrained(&quot;./fine_tuned_bert_page_intent&quot;)<br>tokenizer.save_pretrained(&quot;./fine_tuned_bert_page_intent&quot;)</pre><h4>The Result: A BERT Model That Understands Web Pages</h4><p>After running this process, we end up with a BERT model fine-tuned on high-quality, diverse synthetic data. This model has the potential to classify web pages with between informational, navigational, commercial, and transactional content.</p><p>If you liked the content, be sure to follow for me. Also, follow and Twitter and feel free to reach out</p><ul><li><a href="https://murraycole.com/">Cole Murray - Personal Website</a></li><li><a href="https://x.com/_ColeMurray">x.com</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7d93bf271794" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using LLMs to Build A Code Generation Dataset]]></title>
            <link>https://colemurray.medium.com/using-llms-to-build-a-code-generation-dataset-cae396d2fcaa?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/cae396d2fcaa</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Tue, 23 Jan 2024 20:03:11 GMT</pubDate>
            <atom:updated>2024-01-23T20:03:11.978Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SKndO2HuQ2BpyeZD" /><figcaption>llm robot sweeping up bad code</figcaption></figure><h3>Introduction</h3><p>In this article, you’ll learn how to build a code generation dataset using Large Language Models (LLMs). This tutorial will guide you through scraping code data, cleaning it from various artifacts, and refining it into a structured dataset. We’ll navigate the challenges and demonstrate the power of LLMs in transforming raw code into a valuable resource for code generation.</p><h3>The Journey of Scraping Code</h3><p>Scraping code involves extracting code snippets from various online sources. However, this raw code often contains unwanted elements like line numbers, HTML tags, or commentary that aren’t part of the actual code. Let’s start by scraping some code using Python’s requests library.</p><pre>import requests<br> <br># URL of the webpage where the code is located<br>url = &#39;https://example.com/code-snippet&#39;<br> <br># Sending a GET request to the URL<br>response = requests.get(url)<br> <br># Checking if the request was successful<br>if response.status_code == 200:<br>    # Extracting the text content from the response<br>    raw_html = response.text<br>    print(&quot;html fetched successfully:&quot;)<br>    print(raw_html)<br>else:<br>    print(f&quot;Failed to retrieve page. Status code: {response.status_code}&quot;)</pre><h4>Extracting Code from HTML</h4><p>After fetching the raw HTML content using Python’s requests library, the next challenge is to convert this HTML into a more readable, text-only format. This is where the html2text library becomes useful. It converts HTML into Markdown, which is much closer to the plain text we want. Here’s how you can use html2text to achieve this:</p><pre>import html2text<br> <br># Initialize html2text converter<br>converter = html2text.HTML2Text()<br>converter.ignore_links = True  # Optionally, ignore converting links<br>converter.mark_code = True  # wrap code in [code]...[/code] tags<br> <br># Converting HTML to Markdown<br>markdown_text = converter.handle(raw_html)<br> <br>print(&quot;Converted Markdown text:&quot;)<br>print(markdown_text)<br> <br>code_blocks = re.findall(r&#39;\[code\](.*?)\[/code\]&#39;, markdown_text, re.DOTALL)<br>print(&quot;Code blocks extracted:&quot;)<br>print(code_blocks)</pre><h3>Introducing LLMs in the Cleaning Process</h3><h4>The Initial Challenge</h4><p>Consider the scraped code snippet in our example. It includes line numbers and annotations irrelevant to the actual code. Cleaning this manually is tedious and error-prone.</p><pre>[code]<br>copy<br>    1<br>    2<br>    3<br>    $ curl https://api.openai.com/v1/models \<br>      -H &quot;Authorization: Bearer $OPENAI_API_KEY&quot; \<br>      -H &quot;OpenAI-Organization: YOUR_ORG_ID&quot;<br>[/code]</pre><h4>Using LLMs for Initial Cleaning</h4><p>We can use LLMs to remove these artifacts. Here’s a simplified version of how we might use an LLM like GPT-3.5-turbo:</p><pre>import openai<br> <br># The code snippet with artifacts<br>example = &quot;&quot;&quot;[code] 1 2 3 4...[/code]&quot;&quot;&quot;<br> <br># Basic prompt for the LLM<br>prompt = f&quot;Please clean the following code snippet by removing all non-code elements like line numbers and annotations:\n{example}&quot;<br> <br># Send the request to the OpenAI API<br>response = openai.Completion.create(<br>    model=&quot;gpt-3.5-turbo-1106&quot;,<br>    prompt=prompt,<br>    max_tokens=1000<br>)<br> <br>cleaned_code = response.choices[0].text.strip()<br>print(&quot;Cleaned Code:&quot;)<br>print(cleaned_code)</pre><p>This script sends our code snippet to the LLM, which returns a cleaner version.</p><pre>[code]<br>    curl https://api.openai.com/v1/models \<br>      -H &quot;Authorization: Bearer $OPENAI_API_KEY&quot; \<br>      -H &quot;OpenAI-Organization: YOUR_ORG_ID&quot;<br>[/code]</pre><h4>Cost Considerations</h4><p>Using GPT-3.5-turbo for tasks like code cleaning or parsing documentation webpages, the expected cost per generation with this model ranges from $0.30 to $0.75 per 1000 generations depending on the code snippet length. While this might seem minimal at a glance, the expense can accumulate significantly in large-scale projects.</p><p>If a project entails parsing 100,000 snippets, at the higher end ($0.75 per 1000 generations), this cost escalates to $75. While this isn’t wildly expensive, it’s important to assess whether the complexity of the task justifies the use of such a high-end model.</p><h3>Conclusion</h3><p>In this post, we’ve seen how LLMs can be used to clean code scraped from the web. We’ve also seen how the cost of using such models can add up quickly. In my next post, I’ll show you how to use a cheaper model to achieve the same results.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cae396d2fcaa" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploy a Nextjs Static Site on AWS Cloudfront and S3]]></title>
            <link>https://colemurray.medium.com/deploy-a-nextjs-static-site-on-aws-cloudfront-and-s3-6902e5a9af3d?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/6902e5a9af3d</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[nextjs]]></category>
            <category><![CDATA[javascrıpt]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Thu, 04 Jan 2024 08:09:23 GMT</pubDate>
            <atom:updated>2024-01-04T08:10:25.875Z</atom:updated>
            <content:encoded><![CDATA[<h3>Deploy Nextjs Static Site on AWS Cloudfront and S3</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*iQHpUKevGaKnt91PtAU1aA.png" /></figure><h3>Introduction</h3><p>Recently, I undertook the task of rebuilding my personal website using <a href="https://nextjs.org/">Next.js</a>. My goal was to build a basic static blog using next.js and host it on AWS Cloudfront and S3. Despite finding several tutorials, none seemed to fit my specific requirements, leading me to experiment through trial and error. In this blog post, I aim to share the effective solution I discovered, hoping to streamline this process for others.</p><h3>Prerequisites</h3><p>Before diving into the details, here are the prerequisites:</p><ul><li>A Next.js application ready for deployment.</li><li>An active AWS account with necessary permissions.</li></ul><h3>Preparing Your Next.js Application</h3><p>The first step involves preparing your Next.js application for deployment. Ensure your application is production-ready by running:</p><pre>npm run build</pre><p>and you have next.config.js configured in export mode</p><pre>const nextConfig = {    <br>  output: &#39;export&#39;,    <br>  // other configs<br>}</pre><p>This command generates a out folder containing optimized production builds of your application.</p><h3>Issues with Next.js and AWS Cloudfront</h3><p>While setting up my Next.js application on AWS Cloudfront using a modified <a href="https://dev-kit.io/templates/create-vite-app">dev-kit static build template</a>, I encountered a significant challenge with path routing. This issue arises from the mismatch between the URL path on the website (like site.com/contact) and the corresponding file in the S3 bucket (contact.html).</p><h3>Path Routing Problem</h3><p>In a typical Next.js setup, navigating to site.com/contact expects a contact.html at the root. Most web servers can handle this by serving the contact.html file when the request URI is /contact. However, s3 is not a web server, and only understands key paths.</p><p>Using Next.js’s trailingSlash option creates nested files like contact/index.html, but this still doesn&#39;t solve the problem due to the .html extension mismatch.</p><h3>Solution: Cloudfront Edge Function</h3><p>To overcome this, I implemented a Cloudfront edge function to rewrite incoming request URIs. The function modifies the incoming URI to point to the correct HTML file in the S3 bucket. Below is the TypeScript code for the edge function:</p><pre>exports.handler = async (event) =&gt; {<br>    const request = event.Records[0].cf.request;<br>    const uri = request.uri;<br><br>    if (uri === &#39;/&#39;) {<br>        // turns &quot;/&quot; to &quot;/index.html&quot;<br>        request.uri += &#39;index.html&#39;;<br>    } else if (uri.endsWith(&#39;/&#39;)) {<br>        // turns &quot;/foo/&quot; to &quot;/foo.html&quot;<br>        request.uri = uri.slice(0, -1) + &#39;.html&#39;;<br>    } else if (!uri.includes(&#39;.&#39;)) {<br>        // turns &quot;/foo&quot; to &quot;/foo.html&quot;<br>        request.uri += &#39;.html&#39;;<br>    }<br><br>    return request;<br>};</pre><h3>Integration with AWS CDK</h3><p>For those using the AWS Cloud Development Kit (CDK), integrating this solution is straightforward. Below is a CDK stack example that includes the edge function:</p><pre>import {Certificate} from &#39;aws-cdk-lib/aws-certificatemanager&#39;;<br>import {<br>    CloudFrontWebDistribution,<br>    CloudFrontWebDistributionProps,<br>    OriginAccessIdentity,<br>    ViewerCertificate,<br>} from &#39;aws-cdk-lib/aws-cloudfront&#39;;<br>import {BlockPublicAccess, Bucket} from &#39;aws-cdk-lib/aws-s3&#39;;<br>import {BucketDeployment, ISource} from &#39;aws-cdk-lib/aws-s3-deployment&#39;;<br>import {Construct} from &#39;constructs&#39;;<br>import * as lambda from &#39;aws-cdk-lib/aws-lambda&#39;;<br>import {Runtime, Code} from &#39;aws-cdk-lib/aws-lambda&#39;;<br>import {LambdaEdgeEventType} from &#39;aws-cdk-lib/aws-cloudfront&#39;;<br><br><br>export interface StaticSiteProps {<br>    readonly certificateArn?: string;<br>    readonly domainNames?: string[];<br>    readonly sourceAsset: ISource;<br>}<br><br>export class StaticSiteWithRewrite extends Construct {<br>    constructor(scope: Construct, id: string, props: StaticSiteProps) {<br>        super(scope, id);<br><br>        if ((props.certificateArn &amp;&amp; !props.domainNames) || (!props.certificateArn &amp;&amp; props.domainNames)) {<br>            throw new Error(&#39;Both certificateArn and domainNames must be provided if one is provided.&#39;);<br>        }<br><br>        // Lambda@Edge Function<br>        const edgeLambda = new lambda.Function(this, `${id}EdgeLambda`, {<br>            runtime: Runtime.NODEJS_LATEST,<br>            handler: &#39;index.handler&#39;,<br>            code: Code.fromInline(`<br>exports.handler = async (event) =&gt; {<br>    const request = event.Records[0].cf.request;<br>    const uri = request.uri;<br><br><br>    if (uri === &#39;/&#39;) {<br>        // turns &quot;/&quot; to &quot;/index.html&quot;<br>        request.uri += &#39;index.html&#39;<br>    } else if (uri.endsWith(&#39;/&#39;)) {<br>        // turns &quot;/foo/&quot; to &quot;/foo.html&quot;<br>        request.uri = uri.slice(0, -1) + &#39;.html&#39;<br>    } else if (!uri.includes(&#39;.&#39;)) {<br>        // turns &quot;/foo&quot; to &quot;/foo.html&quot;<br>        request.uri += &#39;.html&#39;<br>    }<br><br>    return request;<br>};<br>      `),<br>        });<br><br>        const bucket = new Bucket(this, `${id}WebsiteBucket`, {<br>            websiteIndexDocument: &#39;index.html&#39;,<br>            blockPublicAccess: BlockPublicAccess.BLOCK_ALL,<br>        });<br><br>        const originAccessIdentity = new OriginAccessIdentity(this, &#39;OAI&#39;);<br>        bucket.grantRead(originAccessIdentity);<br><br>        new BucketDeployment(this, `${id}DeployWebsite`, {<br>            sources: [props.sourceAsset],<br>            destinationBucket: bucket,<br>        });<br><br>        let distributionProps: CloudFrontWebDistributionProps = {<br>            originConfigs: [<br>                {<br>                    s3OriginSource: {<br>                        s3BucketSource: bucket,<br>                        originAccessIdentity: originAccessIdentity,<br>                    },<br>                    behaviors: [<br>                        {<br>                            isDefaultBehavior: true,<br>                            lambdaFunctionAssociations: [{<br>                                eventType: LambdaEdgeEventType.ORIGIN_REQUEST,<br>                                lambdaFunction: edgeLambda.currentVersion,<br>                            }],<br>                        }<br>                    ],<br>                },<br>            ],<br>        };<br><br>        if (props.certificateArn &amp;&amp; props.domainNames) {<br>            distributionProps = {<br>                ...distributionProps,<br>                viewerCertificate: ViewerCertificate.fromAcmCertificate(<br>                    Certificate.fromCertificateArn(this, `${id}certificate`, props.certificateArn),<br>                    {aliases: props.domainNames},<br>                ),<br>            };<br>        }<br><br>        new CloudFrontWebDistribution(this, `${id}WebsiteDistribution`, distributionProps);<br>    }<br>}</pre><p>In this CDK stack, we define a Lambda@Edge function that rewrites the request URI. This ensures that the path routing issue is resolved, making the Next.js application function correctly when hosted on AWS Cloudfront.</p><p>By implementing these solutions, I was able to successfully deploy my Next.js application on AWS Cloudfront and overcome the routing challenges. This approach can be beneficial for anyone facing similar issues with Next.js and AWS Cloudfront integration.</p><p>This article was first published on <a href="https://murraycole.com/posts/deploy-nextjs-on-aws-cloudfront-and-s3">my personal site</a>, click through for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6902e5a9af3d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Enhancing RAG with BAAI/bge-reranker: A Comprehensive Guide]]></title>
            <link>https://colemurray.medium.com/enhancing-rag-with-baai-bge-reranker-a-comprehensive-guide-fe994ba9f82a?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/fe994ba9f82a</guid>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Tue, 19 Dec 2023 18:32:40 GMT</pubDate>
            <atom:updated>2023-12-21T06:56:24.495Z</atom:updated>
            <content:encoded><![CDATA[<h3>Improving Llamaindex RAG performance with ranking</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/900/1*Q5e8DD-3wKgKVqxPmrfuoA.png" /><figcaption>enhancing rag with BAAI/bge-reranker</figcaption></figure><p>Retrieval-Augmented Generation (RAG) has been a game-changer in the field of natural language processing, especially for tasks that blend information retrieval with generative models. As part of my contributions to the field, I have recently implemented support for the FlagEmbeddingReranker in the llama_index library. This tool performs reranking, bringing more accuracy and relevance to the retrieval phase. In this article, I&#39;ll provide a comprehensive tutorial on the usage of FlagEmbeddingReranker, diving into its functionalities, the problems it solves, and its importance in improving RAG systems.</p><h3>Introduction to FlagEmbeddingReranker</h3><p>The FlagEmbeddingReranker is a class in the llama_index library designed for re-ranking nodes (or documents) based on their relevance to a given query. It leverages a pre-trained model to compute relevance scores and select the top N nodes. This re-ranking mechanism is particularly valuable in RAG, where the quality of retrieved documents directly impacts the generation quality.</p><p>The re-ranker can be used with any of the BAAI/bge-reranker models, such as BAAI/bge-reranker-base , BAAI/bge-reranker-large , BAAI/bge-reranker-large-en-v1.5</p><p>You can view the available models <a href="https://huggingface.co/BAAI/bge-reranker-large">here</a></p><h3>Why Use FlagEmbedding Reranking in RAG?</h3><p>The latest BAAI/bge-reranker models, integral to the FlagEmbeddingReranker, are designed to:</p><ul><li><strong>Directly Compute Relevance</strong>: They take a question and document as inputs and directly output a similarity score, providing a more nuanced measure of relevance compared to vector-based embedding models.</li><li><strong>Optimize Scoring Range</strong>: Optimized using cross-entropy loss, these models offer flexibility in scoring, not limited to a specific range.</li><li><strong>Adapt to Specific Use Cases</strong>: Their fine-tuning capabilities make them ideal for re-ranking the top-k documents returned by embedding models, ensuring high relevance and accuracy.</li></ul><h3>Setting Up</h3><p>Before diving into the implementation, ensure you have the llama_index and FlagEmbedding packages installed. If not, install them using:</p><pre>pip install llama-index FlagEmbedding</pre><h3>Implementing FlagEmbeddingReranker</h3><p>Here’s how to incorporate FlagEmbeddingReranker into your RAG setup:</p><h4>1. Import and Initialize</h4><p>First, import necessary classes and initialize FlagEmbeddingReranker.</p><pre>from llama_index.postprocessor.flag_embedding_reranker import FlagEmbeddingReranker<br><br>reranker = FlagEmbeddingReranker(<br>    top_n=3,<br>    model=&quot;BAAI/bge-reranker-large&quot;,<br>    use_fp16=False<br>)</pre><h4>2. Prepare Nodes and Query</h4><p>Assume you have a list of NodeWithScore objects, each representing a document retrieved by your RAG&#39;s initial query phase.</p><pre>from llama_index.schema import NodeWithScore, QueryBundle, TextNode<br><br>documents = [<br>    &quot;Retrieval-Augmented Generation (RAG) combines retrieval and generation for NLP tasks.&quot;,<br>    &quot;Generative Pre-trained Transformer (GPT) is a language generation model.&quot;,<br>    &quot;RAG uses a retriever to fetch relevant documents and a generator to produce answers.&quot;,<br>    &quot;BERT is a model designed for understanding the context of a word in a sentence.&quot;<br>]<br><br>nodes = [NodeWithScore(node=TextNode(text=doc)) for doc in documents]<br>query = &quot;What is RAG in NLP?&quot;</pre><h4>3. Re-Rank Nodes</h4><p>Invoke FlagEmbeddingReranker with the nodes and query.</p><pre>query_bundle = QueryBundle(query_str=query)<br>ranked_nodes = reranker._postprocess_nodes(nodes, query_bundle)</pre><h4>4. Analyze Results</h4><p>The returned ranked_nodes will be a sorted list based on relevance to the query.</p><pre>for node in ranked_nodes:<br>    print(node.node.get_content(), &quot;-&gt; Score:&quot;, node.score)</pre><h3>Expected Output</h3><p>The output should reflect the relevance of each document to the query “What is RAG in NLP?”. Ideally, the document explicitly mentioning RAG and its role in NLP should rank higher.</p><ol><li>“Retrieval-Augmented Generation (RAG) combines retrieval and generation for NLP tasks.” -&gt; Higher score</li><li>“RAG uses a retriever to fetch relevant documents and a generator to produce answers.” -&gt; Next highest score</li></ol><p>Documents about GPT and BERT, while relevant to NLP, are less pertinent to the specific query about RAG and thus should score lower.</p><h3>Conclusion</h3><p>The FlagEmbeddingReranker equipped with the new BAAI/bge-reranker models is a powerful addition to any RAG pipeline. It ensures that your retrieval phase is not just fetching a wide array of documents but is accurately focusing on the most relevant ones. Whether you are developing sophisticated NLP applications or exploring the frontiers of language models, integrating this advanced reranking tool is pivotal in achieving high-quality, relevant outputs.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fe994ba9f82a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Alternative to Vercel: Deploying a Next.js Application on AWS Amplify using AWS CDK]]></title>
            <link>https://javascript.plainenglish.io/alternative-to-vercel-deploying-a-next-js-application-on-aws-amplify-using-aws-cdk-1dd65273cc00?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/1dd65273cc00</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Mon, 16 Oct 2023 12:16:38 GMT</pubDate>
            <atom:updated>2023-10-24T04:12:40.477Z</atom:updated>
            <content:encoded><![CDATA[<h3>Deploying a Next.js Application on AWS Amplify using AWS CDK</h3><h4>A guide on deploying Next.js on AWS amplify with AWS CDK</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QVzQS2RQmm6Yv6H3u02dyA.png" /><figcaption>A screen capture of a developer making this tutorial</figcaption></figure><h3>Table of Contents</h3><ol><li>Introduction</li><li>An Overview of AWS Amplify and Hosting Next.js</li><li>Prerequisites</li><li>Setting Up the Next.js Starter Kit</li><li>Introducing AWS CDK and Its Key Concepts</li><li>Configuring the AWS CDK Stack for Deployment</li><li>Deploying with AWS Amplify</li><li>Tips for Effective Maintenance</li><li>Conclusion</li></ol><h3>Introduction</h3><p>While Vercel stands out as a popular platform for deploying Next.js applications, there are alternative paths that cater to specific requirements and offer greater flexibility. Enter AWS Amplify with AWS CDK. With this guide, we’ll explore the step-by-step process of deploying your Next.js app on AWS Amplify using AWS CDK. Ready to embark on this voyage? Let’s dive right in!</p><h3>An Overview of AWS Amplify and Hosting Next.js</h3><h4>AWS Amplify</h4><p>AWS Amplify is a development platform from Amazon Web Services (AWS) that makes it easy for developers to build and deploy applications. Amplify abstracts the process of configuring cloud services and provides a straightforward way to interact with them.</p><p>Key Features of AWS Amplify:</p><ul><li><strong>Backend Functions</strong>: Simplifies setting up cloud services like authentication, APIs, storage, and more.</li><li><strong>Hosting &amp; CI/CD</strong>: Automated deployment, hosting, and continuous integration/continuous deployment options are available out of the box.</li><li><strong>Scalability</strong>: Built on top of AWS, it offers immense scalability options for your applications.</li><li><strong>Integrated Development</strong>: Amplify’s libraries and UI components help in seamlessly integrating cloud services with your app.</li><li><strong>Monitoring with CloudWatch</strong>: AWS Amplify integrates seamlessly with CloudWatch, offering real-time monitoring of your Next.js application. This allows you to track and diagnose issues, set alarms, and gain insights into application performance and usage patterns.</li></ul><h4>Hosting Next.js on AWS Amplify</h4><p>Next.js, a popular React framework with server-side rendering capabilities, can be efficiently hosted on AWS Amplify. The primary advantages include:</p><ul><li><strong>SSR (Server-Side Rendering)</strong>: AWS Amplify fully supports Next.js’s SSR, allowing for faster page loads and enhanced SEO capabilities.</li><li><strong>Environment Variables</strong>: Easy configuration and usage of environment variables to manage secrets and application settings.</li><li><strong>Continuous Deployment</strong>: Integrated CI/CD from your repository, ensuring that your Next.js app is always up to date on the cloud.</li><li><strong>Branching</strong>: Features like branch-based deployments make it simpler to manage different stages of your application.</li></ul><p>In essence, AWS Amplify offers a comprehensive hosting solution for Next.js, merging the flexibility of AWS infrastructure with the simplicity of frontend-focused deployment.</p><p>— -</p><h3>Prerequisites</h3><p>Before we proceed, ensure:</p><p>- An AWS account is set up<br>- Node.js and npm are installed<br>- AWS CLI is configured with the right permissions<br>- You’re familiar with Next.js, AWS CDK, and pnpm (a fast, disk-space efficient package manager)</p><p>— -</p><h3>Setting Up the Next.js Starter Kit</h3><p>Kickstart your Next.js app:</p><p>1. Initialize a new project: npx create-next-app nextjs-cdk-app <br>2. Enter the project directory: cd nextjs-cdk-app</p><h3>Introducing AWS CDK and Its Key Concepts</h3><p>The AWS Cloud Development Kit (CDK) lets us define cloud resources using familiar programming languages. In this guide, we’re using TypeScript. Here are some elements you should be familiar with:</p><p>- <strong>App</strong>: The main unit where cloud components are defined.<br>- <strong>Stack</strong>: A collection of AWS resources.<br>- <strong>BuildSpec</strong>: A collection of build commands and related settings.</p><h3>Configuring the AWS CDK Stack for Deployment</h3><p>Here’s the meat of our deployment: the CDK Stack. Below is an outline of the steps our provided code will execute:</p><p>1. <strong>Define Role</strong>: The stack starts by defining a role for Amplify. This role has permissions to manage resources for our application. <em>Note: This role is the role for Amplify’s build, and not the runtime role! </em><br>2. <strong>Source Code Provider</strong>: We’re linking our application to a GitHub repository. The GitHub token is stored securely in AWS Secret Manager. Each code change will trigger a rebuild and automatically update.<br>3. <strong>Amplify App Creation</strong>: Here, we configure and create our Amplify app.<br>4. <strong>Main Branch Attachment</strong>: We attach our main branch and define its settings.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1f93a252710f6e56fc6d1fdfdd379e65/href">https://medium.com/media/1f93a252710f6e56fc6d1fdfdd379e65/href</a></iframe><h3>Deploying with AWS Amplify</h3><p>With our stack defined, here’s the step to deploy:</p><p>First, create a configuration file in config.ts</p><pre>export const configuration = {<br>  accessTokenName: &quot;__ACCESS_TOKEN__&quot;,<br>  repoOwner: &quot;__REPO_OWNER__&quot;,<br>  repoName: &quot;__REPO_NAME__&quot;,<br>}</pre><pre>import * as cdk from &#39;aws-cdk-lib&#39;;<br><br>import { AmplifyStack } from &#39;./stack&#39;;<br>import {configuration} from &quot;./config&quot;;<br><br>const app = new cdk.App();<br><br>new AmplifyStack(app, `NextjsStack-${configuration.repoName}`, {<br>  description: &#39;Cloudformation stack containing the Amplify configuration&#39;,<br>});</pre><p>Deploy the CDK stack: cdk deploy</p><p>AWS Amplify will then pick up the changes and initiate the build and deployment process.</p><h3>Tips for Effective Maintenance</h3><ul><li><strong>Regularly Update</strong>: Ensure Next.js, AWS packages, and pnpm are up to date.<br>- <strong>Monitoring</strong>: Use AWS CloudWatch to keep an eye on your application.<br>- <strong>Backups</strong>: Regularly backup your app and database.<br>- <strong>AWS Best Practices</strong>: Stay updated. AWS frequently revises its best practices.</li></ul><h3>Conclusion</h3><p>Kudos! You’ve now deployed a Next.js app on AWS Amplify using AWS CDK. With this robust foundation, the opportunities are endless. You can find the complete code here</p><p><a href="https://github.com/devkit-io/nextjs-amplify-starter-kit">GitHub - devkit-io/nextjs-amplify-starter-kit</a></p><h3>Simplified Deployment</h3><p>If you’re feeling a bit lost with the CDK deployment steps, check out <a href="https://dev-kit.io/managed-nextjs">dev-kit.io/managed-nextjs</a>. Dev-kit will automate the entire starter kit setup and deployment, giving a one-click template deploy into your AWS account, completely free.</p><p>Get started today!</p><p><a href="https://dev-kit.io/managed-nextjs">Host Next.js on AWS: Effortless Deployment Your Own Account</a></p><h3>In Plain English</h3><p><em>Thank you for being a part of our community! Before you go:</em></p><ul><li><em>Be sure to </em><strong><em>clap</em></strong><em> and </em><strong><em>follow</em></strong><em> the writer! 👏</em></li><li><em>You can find even more content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><strong><em> 🚀</em></strong></li><li><em>Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. 🗞️</em></li><li><em>Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a><strong><em>(X</em></strong>), <a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a>, <a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong><em>YouTube</em></strong></a>, and <a href="https://discord.gg/in-plain-english-709094664682340443"><strong><em>Discord</em></strong></a><strong><em>.</em></strong></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1dd65273cc00" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/alternative-to-vercel-deploying-a-next-js-application-on-aws-amplify-using-aws-cdk-1dd65273cc00">Alternative to Vercel: Deploying a Next.js Application on AWS Amplify using AWS CDK</a> was originally published in <a href="https://javascript.plainenglish.io/">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a CI/CD Pipeline for a Serverless Express Application with AWS CDK]]></title>
            <link>https://itnext.io/building-a-ci-cd-pipeline-for-a-serverless-express-application-with-aws-cdk-1d3c842ea1ff?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/1d3c842ea1ff</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Mon, 04 Sep 2023 18:33:36 GMT</pubDate>
            <atom:updated>2023-09-05T03:56:37.463Z</atom:updated>
            <content:encoded><![CDATA[<h3>Building a CI/CD Pipeline for a Serverless Express Lambda Application with AWS CDK</h3><figure><img alt="A visualization of the result of deploying this application" src="https://cdn-images-1.medium.com/max/1024/1*a-AGQuQvz2iikXTlcl1LJA.png" /><figcaption>An image showing the result of this tutorial</figcaption></figure><p>Ever wondered how the top tech companies deploy their applications so seamlessly? It all starts with an efficient CI/CD pipeline, the assembly line of the software world. In today’s fast-paced software development environment, mastering this process is crucial for delivering high-quality applications. But there’s another piece to the puzzle: ‘infrastructure as code.’ Imagine being able to write, test, and deploy your entire infrastructure using code! Sounds intriguing?</p><p>In this blog post, we will explore how to build a CI/CD pipeline for a serverless express.js backend application using AWS CDK (Cloud Development Kit). By using serverless architecture, you’ll not only streamline your development but also significantly reduce operating costs. By the end of this post, you’ll have a</p><ul><li>full CI/CD pipeline</li><li>staging and production environment</li><li>serverless-express lambda function</li><li>error alarm with pipeline rollback functionality</li></ul><h3>Table of Contents</h3><ol><li>Prerequisites</li><li>High Level Architecture</li><li>Serverless Express</li><li>Backend Pipeline Stack CDK</li><li>Lambda Construct</li><li>Service API Stack</li><li>Deploying the project</li></ol><h3>Prerequisites:</h3><ul><li>Understanding of Express.js</li><li>Basic understanding of AWS CDK</li><li>Docker installed</li></ul><p>Complete code can be found here:</p><p><a href="https://github.com/ColeMurray/serverless-express-lambda-cdk">GitHub - ColeMurray/serverless-express-lambda-cdk: An express serverless lambda project deployed with AWS CDK</a></p><h3>Glossary</h3><ul><li><strong>CI/CD Pipeline</strong>: Continuous Integration and Continuous Deployment/Delivery. It’s an automated process that allows code changes to be automatically built, tested, and deployed to production environments. This practice enhances software development speed, quality, and reliability.</li><li><strong>AWS CDK (Amazon Web Services Cloud Development Kit)</strong>: A software development framework used to define cloud infrastructure as code (IAC) and provision it through AWS CloudFormation. The CDK allows developers to define resources using familiar programming languages such as Python, TypeScript, and Java, enabling more reusable and modular cloud service deployments.</li><li><strong>Express.js</strong>: A fast, unopinionated, minimalist web framework for Node.js, designed to simplify the process of building web applications and APIs. It provides a robust set of features for web and mobile applications, including routing, middleware support, and template engines, allowing for rapid development and deployment.</li></ul><h3>High-Level Architecture</h3><h4>Deployment Pipeline</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FCFu3xrf4SNdhCNXF-G4ag.png" /><figcaption>Application pipeline</figcaption></figure><h4>Application Architecture</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/319/1*eZXOQYiiUfwxjvX7yazlnw.png" /><figcaption>basic application architecture</figcaption></figure><h3>Serverless Express</h3><p>Serverless Express is a powerful solution that allows developers to run REST APIs and other web applications using popular Node.js application frameworks such as Express, Koa, Hapi, Sails, and more. The beauty of Serverless Express lies in its ability to host these applications on scalable and cost-effective platforms like AWS Lambda and Amazon API Gateway or Azure Function while being able to use express.js for local development.</p><p>In this code block, we are setting up a serverless Express.js application using the @vendia/serverless-express package, which enables you to run your Express app on AWS Lambda and API Gateway.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/af46fc0da75743fef5bb4b5815198ea0/href">https://medium.com/media/af46fc0da75743fef5bb4b5815198ea0/href</a></iframe><p>Here, we define our express middleware, as well as our api routes.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/14ff830c233a667da1da905997846fc3/href">https://medium.com/media/14ff830c233a667da1da905997846fc3/href</a></iframe><h3>Class Definition: BackendPipelineStack</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/363245963a02c033fc0964b085df9a6b/href">https://medium.com/media/363245963a02c033fc0964b085df9a6b/href</a></iframe><p>The BackendPipelineStack class extends the CDK&#39;s Stack class, enabling the orchestration of various AWS resources.</p><h4>Properties</h4><p>The class accepts properties defined in the PipelineStackProps interface:</p><ul><li><strong>Repo Name</strong>: The repository name for your backend code.</li><li><strong>Branch</strong>: The branch to pull the code from.</li><li><strong>Connection ARN</strong>: Amazon Resource Name for the connection.</li><li><strong>Pre-Prod and Prod Accounts</strong>: Account and region details for pre-production and production environments.</li><li><strong>Cross Environment Deployment</strong>: Optional flag for enabling cross-account keys.</li></ul><h3>Source Configuration</h3><p>First, a CodePipelineSource is created by specifying the repository name, branch, and connection ARN. This source configures the origin of the code that will be built and deployed.</p><p>You can create a connection within code pipeline here:</p><p><a href="https://us-west-2.console.aws.amazon.com/codesuite/settings/connections/create?origin=settings&amp;region=us-west-2">https://us-west-2.console.aws.amazon.com/codesuite/settings/connections/create?origin=settings&amp;region=us-west-2</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-3tdTmhShrb1VhA88Gtblg.png" /><figcaption>AWS Codepipeline connections UI</figcaption></figure><h3>Synthesis Step</h3><p>The synthesis (synth) step is responsible for building the application. In this code, it involves the following commands:</p><ul><li>Navigating to the deployment directory.</li><li>Installing dependencies using npm ci.</li><li>Building the project with npm run build.</li><li>Synthesizing the CDK resources using npx cdk synth.</li></ul><h3>Pipeline Creation</h3><p>A CodePipeline is created to orchestrate the build and deployment:</p><ul><li>Cross Account Keys: Allows or restricts cross-account access.</li><li>Synthesis Step: The aforementioned synthesis step.</li><li>Self Mutation: If set to true, the pipeline will automatically update itself when changes are made to its definition.</li><li>CodeBuild Defaults: Specifies the environment and policies for the build process.</li></ul><h3>Staging</h3><p>The pipeline is divided into stages, including pre-production (preprod) and production (prod). These stages are created using the BackendServiceStage class, which encapsulates the logic for deploying the backend services.</p><ul><li>Pre-Production Stage: This stage is added to the pipeline without any prerequisites.</li><li>Production Stage: Before deploying to production, a manual approval step is included. This ensures that changes are reviewed before being promoted to the production environment.</li></ul><h3>Lambda Construct</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2667e5b01a9ce07f46563c2e7c509891/href">https://medium.com/media/2667e5b01a9ce07f46563c2e7c509891/href</a></iframe><p>AWS CDK provides a powerful way to encapsulate complex constructs, allowing developers to build reusable modules. This construct represents an AWS Lambda function that’s ready for deployment, along with some error monitoring and deployment strategies.</p><p>Here’s a deep dive into what this construct does:</p><h4><strong>Properties</strong></h4><p>The ApprovedNodeLambda construct accepts properties defined in the ApprovedNodeLambdaProps interface, such as:</p><ul><li><strong>Alarm Threshold</strong>: Defines a threshold of errors for triggering an alarm.</li><li><strong>Code Directory:</strong> The directory containing the source code.</li><li><strong>Build Commands:</strong> Optional build commands and environment for the Lambda function.</li><li><strong>Runtime Settings:</strong> These include the memory size, runtime duration, and environment variables.</li></ul><h4><strong>Code Asset Definition</strong></h4><p>First, the construct defines an asset code by reading from the provided code directory and bundling it using a Docker image for Node.js 18.x. The code asset includes commands for installing dependencies, running a build, and copying the necessary files.</p><h4>Lambda Function Definition</h4><p>A Lambda function is created with the following properties:</p><ul><li>Runtime: It uses Node.js 18.x.</li><li>Timeout: A timeout period for execution, with a default value of 1 minute.</li><li>Memory Size: The amount of memory available for the function, defaulting to 2048 MB.</li><li>Environment Variables: Optional environment variables to pass to the runtime.</li></ul><h4>Error Metrics and Alarm</h4><p>The construct sets up a CloudWatch metric to monitor the ‘Errors’ metric for the Lambda function. An alarm is also created based on this metric, with a configurable threshold and evaluation period. If the error count surpasses the threshold, the alarm is triggered.</p><h4>Lambda Deployment Group</h4><p>Finally, an alias named ‘Current’ is created to represent the current version of the Lambda function. A LambdaDeploymentGroup is defined with this alias, setting up a linear deployment strategy that deploys 10% of the changes every minute. The alarm previously created is also associated with this deployment group.</p><h3>Service Stack: Constructing the API Gateway</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a835bd98eacd9f575f08e5dbc93fda02/href">https://medium.com/media/a835bd98eacd9f575f08e5dbc93fda02/href</a></iframe><p>The DeploymentStack class is responsible for deploying the backend server, Lambda function, and defining the API Gateway&#39;s characteristics. Here&#39;s a walkthrough:</p><h4>Lambda Function Definition</h4><p>First, an instance of ApprovedNodeLambda is created to define the backend server Lambda function. This is where we specify the code directory, handler, and runtime environment.</p><pre>const serverFunction = new ApprovedNodeLambda(this, &#39;backend-server&#39;, {<br>  codeDir: &#39;../source/&#39;,<br>  description: &#39;backend server lambda function&#39;,<br>  handler: &#39;src/lambdaServer.handler&#39;,<br>  runtimeEnvironment: props.envVars ?? {}<br>});</pre><h4>API Gateway Definition</h4><p>Next, we create an <a href="https://aws.amazon.com/api-gateway/">API Gateway</a>, giving it a name and description. The binaryMediaTypes property is defined to accept all media types.</p><pre>const api = new RestApi(this, &#39;api&#39;, {<br>  restApiName: &#39;BackendApi&#39;,<br>  description: &#39;Api gateway for backend api&#39;,<br>  binaryMediaTypes: [&#39;*/*&#39;]<br>});</pre><h4>CORS Configuration and Integration</h4><p>Finally, we configure the CORS policy and set the Lambda integration with the API root. This defines how the backend should interact with requests from different origins.</p><h3>Backend Service Stage: Organizing Deployment Stages</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/54819ed55eccd8e408b83c8a55582ac7/href">https://medium.com/media/54819ed55eccd8e408b83c8a55582ac7/href</a></iframe><p>The BackendServiceStage class represents a specific stage of deployment. It is used to define various deployment environments, such as development, testing, or production as well as other stacks that should deployed as part of this stage.</p><h3>Deploying the Project</h3><p>Update the configuration file</p><pre>export const config = {<br>  codeRepository: &quot;&lt;YourCode/repo&gt;,<br>  codeBranch: &lt;BRANCH&gt;&quot;,<br>  connectionArn: &quot;arn:aws:codestar-connections:us-west-2:&lt;ACCOUNT_ID&gt;:connection/&lt;CONNECTION_ID&gt;&quot;,<br>  preprodAccount: {<br>    account: &quot;&lt;ACCOUNT_ID&gt;&quot;,<br>    region: &quot;&lt;REGION_NAME&gt;&quot;<br>  },<br>  prodAccount: {<br>    account: &quot;&lt;ACCOUNT_ID&gt;&quot;,<br>    region: &quot;&lt;REGION_NAME&gt;&quot;<br>  },<br>  crossEnvDeployqment: false<br>}</pre><p>To deploy the project, run the aws-cdk command</p><pre>npm install<br>npx cdk deploy</pre><p>After the deployment completes, you can view your pipeline. You may need to update the below url specific to your AWS region</p><p><a href="https://us-west-2.console.aws.amazon.com/codesuite/codepipeline/pipelines?region=us-west-2">https://us-west-2.console.aws.amazon.com/codesuite/codepipeline/pipelines?region=us-west-2</a></p><p>Complete code can be found here</p><p><a href="https://github.com/ColeMurray/serverless-express-lambda-cdk/tree/main/deployment">serverless-express-lambda-cdk/deployment at main · ColeMurray/serverless-express-lambda-cdk</a></p><h3>Conclusion</h3><p>By leveraging AWS CDK, we have successfully built a CI/CD pipeline for our backend application. This pipeline automatically triggers whenever changes are made to the repository, builds the application, and deploys it to both pre-production and production environments. With the ability to define infrastructure as code, we can easily manage and scale our backend application with confidence.</p><p>AWS CDK provides a powerful and flexible way to define and manage cloud resources, making it an excellent choice for building CI/CD pipelines. By automating the deployment process, we can reduce manual errors, increase efficiency, and deliver high-quality applications to our users.</p><p><a href="https://colemurray.medium.com/subscribe">Get an email whenever Cole Murray publishes.</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1d3c842ea1ff" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/building-a-ci-cd-pipeline-for-a-serverless-express-application-with-aws-cdk-1d3c842ea1ff">Building a CI/CD Pipeline for a Serverless Express Application with AWS CDK</a> was originally published in <a href="https://itnext.io/">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to build an age and gender multi-task predictor with deep learning in TensorFlow]]></title>
            <link>https://medium.com/free-code-camp/how-to-build-an-age-and-gender-multi-task-predictor-with-deep-learning-in-tensorflow-20c28a1bd447?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/20c28a1bd447</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[tensorflow]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Wed, 12 Dec 2018 17:21:07 GMT</pubDate>
            <atom:updated>2019-01-22T04:28:53.894Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*EU3eKPw1MxH_0HSkto9Pfg.jpeg" /><figcaption>Source: <a href="https://www.governmentciomedia.com/ai-takes-face-recognition-new-frontiers">https://www.governmentciomedia.com/ai-takes-face-recognition-new-frontiers</a></figcaption></figure><p><a href="https://medium.freecodecamp.org/building-an-image-caption-generator-with-deep-learning-in-tensorflow-a142722e9b1f">In my last tutorial</a>, you learned about how to combine a convolutional neural network and Long short-term memory (LTSM) to create captions given an image. In this tutorial, you’ll learn how to build and train a multi-task machine learning model to predict the age and gender of a subject in an image.</p><h3><strong>Overview</strong></h3><ul><li>Introduction to age and gender model</li><li>Building a Multi-task Tensorflow Estimator</li><li>Training</li></ul><h3>Prerequisites</h3><ul><li>basic understanding of convolutional neural networks (CNN)</li><li>basic understanding of TensorFlow</li><li>GPU (optional)</li></ul><h3>Introduction to Age and Gender Model</h3><p>In 2015, researchers from Computer Vision Lab, D-ITET, published a paper <a href="https://www.cv-foundation.org/openaccess/content_iccv_2015_workshops/w11/papers/Rothe_DEX_Deep_EXpectation_ICCV_2015_paper.pdf">DEX</a> and made public their <a href="https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/">IMDB-WIKI</a> consisting of 500K+ face images with age and gender labels.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qQJwCUF-vuGEAd0W.png" /><figcaption>IMDB-WIKI Dataset source: <a href="https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/">https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/</a></figcaption></figure><p>DEX outlines an neural network architecture involving a pretrained imagenet vgg16 model that estimates the apparent age in face images. DEX placed first in <a href="http://chalearnlap.cvc.uab.es/">ChaLearn LAP 2015</a> — a competition that deals with recognizing people in an image — outperforming human reference.</p><h4><strong>Age as a classification problem</strong></h4><p>A conventional way of tackling an age estimation problem with an image as input would be using a regression-based model with mean-squared error as the loss function. DEX models this problem as a classification task, using a softmax classifier with each age represented as a unique class ranging from 1 to 101 and cross-entropy as the loss function.</p><h4><strong>Multi-task learning</strong></h4><p>Multi-task learning is a technique of training on multiple tasks through a shared architecture. Layers at the beginning of the network will learn a joint generalized representation, preventing overfitting to a specific task that may contain noise.</p><p>By training with a multi-task network, the network can be trained in parallel on both tasks. This reduces the infrastructure complexity to only one training pipeline. Additionally, the computation required for training is reduced as both tasks are trained simultaneously.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2aq7M6sgJ7bglCrvsredyA.png" /><figcaption>Multi-task CNN source: https://murraycole.com</figcaption></figure><h3>Building a multi-task network in TensorFlow</h3><p>Below you’ll use TensorFlow’s estimator abstraction to create the model. The model will be trained from raw image input to predict the age and gender of the face image.</p><h4><strong>Project Structure</strong></h4><pre>.<br>├── Dockerfile<br>├── age_gender_estimation_tutorial<br>│   ├── cnn_estimator.py<br>│   ├── cnn_model.py<br>│   └── dataset.py<br>├── bin<br>│   ├── download-imdb.sh<br>│   ├── predict.py<br>│   ├── preprocess_imdb.py<br>│   └── train.py<br>├── requirements.txt</pre><h4><strong>Environment</strong></h4><p>For the environment, you’ll use <a href="https://www.docker.com/">Docker</a> to install dependencies. A GPU version is also provided for convenience.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9e00dc91de3423ba7538431a0725b0b5/href">https://medium.com/media/9e00dc91de3423ba7538431a0725b0b5/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3439e89fafe1c5a6015d1f2f02306bbc/href">https://medium.com/media/3439e89fafe1c5a6015d1f2f02306bbc/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f574663becb932096153c2496ced41ab/href">https://medium.com/media/f574663becb932096153c2496ced41ab/href</a></iframe><pre>docker build -t colemurray/age-gender-estimation-tutorial -f Dockerfile .</pre><h4>Data</h4><p>To train this model, you’ll use the IMDB-WIKI dataset, consisting of 500K+ images. For simplicity, you’ll download the pre-cropped imdb images (7GB). Run the script below to download the data.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a9a0063783f2926145ffb1008273e2a1/href">https://medium.com/media/a9a0063783f2926145ffb1008273e2a1/href</a></iframe><pre>chmod +x bin/download-imdb-crop.sh</pre><pre>./bin/download-imdb-crop.sh</pre><p><strong>Preprocessing</strong></p><p>You’ll now process the dataset to clean out low-quality images and crop the input to a fixed image size. Additionally, you’ll format the data as a CSV to simplify reading into TensorFlow.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1c2c21464b7bc1b1a447206fa7712540/href">https://medium.com/media/1c2c21464b7bc1b1a447206fa7712540/href</a></iframe><pre>docker run -v $PWD:/opt/app \<br>-e PYTHONPATH=$PYTHONPATH:/opt/app \<br>-it colemurray/age-gender-estimation-tutorial \<br>python3 /opt/app/bin/preprocess_imdb.py \<br>--db-path /opt/app/data/imdb_crop/imdb.mat \<br>--photo-dir /opt/app/data/imdb_crop \<br>--output-dir /opt/app/var \<br>--min-score 1.0 \<br>--img-size 224</pre><p>After approximately 20 minutes, you’ll have a processed dataset.</p><p>Next, you’ll use TensorFlow’s data pipeline module<a href="https://www.tensorflow.org/api_docs/python/tf/data"> </a><a href="https://www.tensorflow.org/api_docs/python/tf/data">tf.data</a> to provide data to the estimator. Tf.data is an abstraction to read and manipulate a dataset in parallel, utilizing C++ threads for performance.</p><p>Here, you’ll utilize TensorFlow’s CSV Reader to parse the data, preprocess the images, create batches, and shuffle.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/01e2ebac86b8aa7359b040ee3a7a1449/href">https://medium.com/media/01e2ebac86b8aa7359b040ee3a7a1449/href</a></iframe><h4>Model</h4><p>Below, you’ll create a basic CNN model. The model consists of three convolutions and two fully connected layers, with a softmax classifier head for each task.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ed2cf2bb1eebb519449ce6b900d6b45f/href">https://medium.com/media/ed2cf2bb1eebb519449ce6b900d6b45f/href</a></iframe><h4>Joint loss function</h4><p>For the training operation, you’ll use the Adam Optimizer. For a loss function, you’ll average the cross-entropy error of each head, creating a shared loss function between the heads.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/460/1*GmnF07fG1hBbzjcxeNfSng.gif" /><figcaption>age and gender joint loss function</figcaption></figure><h4>TensorFlow estimator</h4><p>TensorFlow estimators provide a simple abstraction for graph creation and runtime processing. TensorFlow has specified an interface model_fn, that can be used to create custom estimators.</p><p>Below, you’ll take the network created above and create training, eval, and predict. These specifications will be used by TensorFlow’s estimator class to alter the behavior of the graph.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dc536a2696e699b2acc57840038ab449/href">https://medium.com/media/dc536a2696e699b2acc57840038ab449/href</a></iframe><h3>Train</h3><p>Now that you’ve preprocessed the data and created the model architecture and data pipeline, you’ll begin training the model.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0905593cd78ddec05be94a86d91c2161/href">https://medium.com/media/0905593cd78ddec05be94a86d91c2161/href</a></iframe><pre>docker run -v $PWD:/opt/app \<br>-e PYTHONPATH=$PYTHONPATH:/opt/app \<br>-it colemurray/age-gender-estimation-tutorial:gpu \<br>python3 /opt/app/bin/train.py \<br>--img-dir /opt/app/var/crop \<br>--train-csv /opt/app/var/train.csv \<br>--val-csv /opt/app/var/val.csv \<br>--model-dir /opt/app/var/cnn-model \<br>--img-size 224 \<br>--num-steps 200000</pre><h3>Predict</h3><p>Below, you’ll load your age and gender TensorFlow model. The model will be loaded from disk and predict on the provided image.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d993d8f1185fbbb0da5cc401a0665abb/href">https://medium.com/media/d993d8f1185fbbb0da5cc401a0665abb/href</a></iframe><pre># Update the model path below with your model<br>docker run -v $PWD:/opt/app \<br>-e PYTHONPATH=$PYTHONPATH:/opt/app \<br>-it colemurray/age-gender-estimation-tutorial \<br>python3 /opt/app/bin/predict.py \<br>--image-path /opt/app/var/crop/25/nm0000325_rm2755562752_1956-1-7_2002.jpg \<br>--model-dir /opt/app/var/cnn-model-3/serving/<strong>&lt;TIMESTAMP&gt;</strong></pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/173/1*wBuO3TbAEa98-0LeQWSBfA.jpeg" /><figcaption>Predicted: M/46 Actual: M/46</figcaption></figure><h3>Conclusion</h3><p>In this tutorial, you learned how to build and train a multi-task network for predicting a subject’s age and image. By using a shared architecture, both targets can be trained and predicted simultaneously.</p><p>Next Steps:</p><ul><li>Evaluate on Your Own Dataset</li><li>Try a different network architecture</li><li>Experiment with Different Hyperparameters</li></ul><p>Questions/issues? Open an issue <a href="https://github.com/ColeMurray/age-gender-estimation-tutorial/issues">here on GitHub</a></p><p>Complete code <a href="https://github.com/ColeMurray/age-gender-estimation-tutorial">here</a>.</p><h3>Call to Action</h3><p>If you enjoyed this tutorial, follow and recommend!</p><p>Interested in learning more about Deep Learning / Machine Learning? Check out my other tutorials:</p><p><a href="https://medium.freecodecamp.org/building-an-image-caption-generator-with-deep-learning-in-tensorflow-a142722e9b1f">- Building an image caption generator with Deep Learning in Tensorflow</a></p><p><a href="https://hackernoon.com/building-a-facial-recognition-pipeline-with-deep-learning-in-tensorflow-66e7645015b8">- Building a Facial Recognition Pipeline with Deep Learning in Tensorflow</a></p><p><a href="https://medium.com/p/cba6efe0acc2">- Deep Learning CNN’s in Tensorflow with GPUs</a></p><p><a href="https://medium.com/google-cloud/keras-inception-v3-on-google-compute-engine-a54918b0058">- Deep Learning with Keras on Google Compute Engine</a></p><p><a href="https://medium.com/google-cloud/recommendation-systems-with-spark-on-google-dataproc-bbb276c0dafd">- Recommendation Systems with Apache Spark on Google Compute Engine</a></p><p>Other places you can find me:</p><p><a href="https://twitter.com/@_colemurray">Cole Murray (@_ColeMurray) | Twitter</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=20c28a1bd447" width="1" height="1" alt=""><hr><p><a href="https://medium.com/free-code-camp/how-to-build-an-age-and-gender-multi-task-predictor-with-deep-learning-in-tensorflow-20c28a1bd447">How to build an age and gender multi-task predictor with deep learning in TensorFlow</a> was originally published in <a href="https://medium.com/free-code-camp">We’ve moved to freeCodeCamp.org/news</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an image caption generator with Deep Learning in Tensorflow]]></title>
            <link>https://medium.com/free-code-camp/building-an-image-caption-generator-with-deep-learning-in-tensorflow-a142722e9b1f?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/a142722e9b1f</guid>
            <category><![CDATA[tech]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Wed, 11 Apr 2018 15:03:07 GMT</pubDate>
            <atom:updated>2018-04-11T16:10:05.356Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YzdxLQkXFqpdiLVeeLJhpw.jpeg" /><figcaption>Generated Caption: A reader successfully completing this tutorial</figcaption></figure><p>In my <a href="https://hackernoon.com/building-a-facial-recognition-pipeline-with-deep-learning-in-tensorflow-66e7645015b8">last tutorial</a>, you learned how to create a facial recognition pipeline in Tensorflow with convolutional neural networks. In this tutorial, you’ll learn how a <strong>convolutional neural network</strong> (CNN) and <strong>Long Short Term Memory</strong> (LSTM) can be combined to create an image caption generator and generate captions for your own images.</p><h3>Overview</h3><ul><li>Introduction to Image Captioning Model Architecture</li><li>Captions as a Search Problem</li><li>Creating Captions in Tensorflow</li></ul><h4>Prerequisites</h4><ul><li>Basic understanding of Convolutional Neural Networks</li><li>Basic understanding of LSTM</li><li>Basic understanding of Tensorflow</li></ul><h3>Introduction to image captioning model architecture</h3><h4>Combining a CNN and LSTM</h4><p>In 2014, researchers from Google released a paper, <a href="https://arxiv.org/pdf/1411.4555.pdf">Show And Tell: A Neural Image Caption Generator</a>. At the time, this architecture was state-of-the-art on the MSCOCO dataset. It utilized a CNN + LSTM to take an image as input and output a caption.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E90mI7YT9F0J6b9EadxfzA.png" /><figcaption>A CNN-LSTM Image Caption Architecture <a href="https://arxiv.org/pdf/1411.4555.pdf">source</a></figcaption></figure><h4>Using a CNN for image embedding</h4><p>A convolutional neural network can be used to create a dense feature vector. This dense vector, also called an embedding, can be used as feature input into other algorithms or networks.</p><p>For an image caption model, this embedding becomes a dense representation of the image and will be used as the initial state of the LSTM.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/172/1*tCeGt4fuK_gX1fh8OSyz1Q.png" /><figcaption>Mapping input to embedding <a href="https://www.slideshare.net/BhaskarMitra3/vectorland-brief-notes-from-using-text-embeddings-for-search">source</a></figcaption></figure><h4>LSTM</h4><p>An LSTM is a recurrent neural network architecture that is commonly used in problems with temporal dependences. It succeeds in being able to capture information about previous states to better inform the current prediction through its memory cell state.</p><p>An LSTM consists of three main components: a forget gate, input gate, and output gate. Each of these gates is responsible for altering updates to the cell’s memory state.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J5W8FrASMi93Z81NlAui4w.png" /><figcaption>An unrolled LSTM <a href="https://colah.github.io/posts/2015-08-Understanding-LSTMs/">source</a></figcaption></figure><p>For a deeper understanding of LSTM’s, visit <a href="https://colah.github.io/posts/2015-08-Understanding-LSTMs/">Chris Olah’s post</a>.</p><h4><strong>Prediction with image as initial state</strong></h4><p>In a sentence language model, an LSTM is predicting the next word in a sentence. Similarly, in a character language model, an LSTM is trying to predict the next character, given the context of previously seen characters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VWHR9w-zv8d20TRGs7DUFQ.png" /><figcaption>Sentence and character model predictions <a href="https://www.youtube.com/watch?v=UXW6Cs82UKo">source</a></figcaption></figure><p>In an image caption model, you will create an embedding of the image. This embedding will then be fed as initial state into an LSTM. This becomes the first previous state to the language model, influencing the next predicted words.</p><p>At each time-step, the LSTM considers the previous cell state and outputs a prediction for the most probable next value in the sequence. This process is repeated until the end token is sampled, signaling the end of the caption.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y4p7N71LK38smrjVsMyhiw.png" /><figcaption>Sampling characters from an LSTM. <a href="https://www.youtube.com/watch?v=UXW6Cs82UKo">source</a></figcaption></figure><h3><strong>Captions as a search problem</strong></h3><p>Generating a caption can be viewed as a graph search problem. Here, the nodes are words. The edges are the probability of moving from one node to another. Finding the optimal path involves maximizing the total probability of a sentence.</p><p>Sampling and choosing the most probable next value is a <a href="https://en.wikipedia.org/wiki/Greedy_algorithm">greedy</a> approach to generating a caption. It is computationally efficient, but can lead to a sub-optimal result.</p><p>Given all possible words, it would not be computationally/space efficient to calculate all possible sentences and determine the optimal sentence. This rules out using a search algorithm such as Depth First Search or Breadth First Search to find the optimal path.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/847/1*_rTQDUNkvkG_yTTBdadOSg.png" /><figcaption><a href="http://blog.murraycole.com/wp-content/uploads/2018/04/sentence_explore_graph.png.png">source</a></figcaption></figure><h4><strong>Beam Search</strong></h4><p>Beam search is a breadth-first search algorithm that explores the most promising nodes. It generates all possible next paths, keeping only the top N best candidates at each iteration.</p><p>As the number of nodes to expand from is fixed, this algorithm is space-efficient and allows more potential candidates than a best-first search.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LB1wsEavM6t7C7A85s1dUg.png" /><figcaption>Beam search for building a sentence. <a href="https://www.youtube.com/watch?v=UXW6Cs82UKo">source</a></figcaption></figure><h3>Review</h3><p>Up to this point, you’ve learned about creating a model architecture to generate a sentence, given an image. This is done by utilizing a CNN to create a dense embedding and feeding this as initial state to an LSTM. Additionally, you’ve learned how to generate better sentences with beam search.</p><p>In the next section, you’ll learn to generate captions from a pre-trained model in Tensorflow.</p><h3>Creating captions in Tensorflow</h3><pre># Project Structure</pre><pre>├── Dockerfile<br>├── bin<br>│ └── download_model.py<br>├── etc<br>│ ├── show-and-tell-2M.zip<br>│ ├── show-and-tell.pb<br>│ └── word_counts.txt<br>├── imgs<br>│ └── trading_floor.jpg<br>├── medium_show_and_tell_caption_generator<br>│ ├── __init__.py<br>│ ├── caption_generator.py<br>│ ├── inference.py<br>│ ├── model.py<br>│ └── vocabulary.py<br>└── requirements.txt</pre><h4>Environment setup</h4><p>Here, you’ll use <strong>Docker</strong> to install <strong>Tensorflow</strong>.</p><p>Docker is a container platform that simplifies deployment. It solves the problem of installing software dependencies onto different server environments. If you are new to Docker, you can read more <a href="https://www.docker.com/">here</a>. To install Docker, run:</p><pre>curl <a href="https://get.docker.com/">https://get.docker.com</a> | sh</pre><p>After installing Docker, you’ll create two files. A <strong>requirements.txt </strong>for the Python dependencies and a <strong>Dockerfile </strong>to create your Docker environment.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/54799e87fd3b15c2e88c0fb0b2e827e1/href">https://medium.com/media/54799e87fd3b15c2e88c0fb0b2e827e1/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/66a1ec68f84e1b0f40ddbf12acc28d8f/href">https://medium.com/media/66a1ec68f84e1b0f40ddbf12acc28d8f/href</a></iframe><p>To build this image, run:</p><pre>$ docker build -t colemurray/medium-show-and-tell-caption-generator -f Dockerfile .</pre><pre># On MBP, ~ 3mins<br># Image can be pulled from dockerhub below</pre><p>If you would like to avoid building from source, the image can be pulled from dockerhub using:</p><pre>docker pull colemurray/medium-show-and-tell-caption-generator # Recommended</pre><h4>Download the model</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zKDLRi58_Lq5cTuLDGCIIA.png" /><figcaption>Show and Tell Inference Architecture <a href="http://blog.murraycole.com/wp-content/uploads/2018/04/show_and_tell_inception_expanded.png">source</a></figcaption></figure><p>Below, you’ll download the model graph and pre-trained weights. These weights are from a training session on the <a href="http://cocodataset.org/#home">MSCOCO dataset</a> for 2MM iterations.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6899b82104b1f90032d002aa111c37d6/href">https://medium.com/media/6899b82104b1f90032d002aa111c37d6/href</a></iframe><p>To download, run:</p><pre>docker run -e PYTHONPATH=$PYTHONPATH:/opt/app -v $PWD:/opt/app \<br>-it colemurray/medium-show-and-tell-caption-generator \<br>python3 /opt/app/bin/download_model.py \<br>--model-dir /opt/app/etc</pre><p>Next, create a model class. This class is responsible for loading the graph, creating image embeddings, and running an inference step on the model.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/db619cf915005dab502271d905d27aa4/href">https://medium.com/media/db619cf915005dab502271d905d27aa4/href</a></iframe><h4><strong>Download the vocabulary</strong></h4><p>When training an LSTM, it is standard practice to tokenize the input. For a sentence model, this means mapping each unique word to a unique numeric id. This allows the model to utilize a softmax classifier for prediction.</p><p>Below, you’ll download the vocabulary used for the pre-trained model and create a class to load it into memory. Here, the line number represents the numeric id of the token.</p><pre># File structure<br># token num_of_occurrances</pre><pre># on 213612<br># of 202290<br># the 196219<br># in 182598</pre><pre>curl -o etc/word_counts.txt <a href="https://raw.githubusercontent.com/ColeMurray/medium-show-and-tell-caption-generator/master/etc/word_counts.txt">https://raw.githubusercontent.com/ColeMurray/medium-show-and-tell-caption-generator/master/etc/word_counts.txt</a></pre><p>To store this vocabulary in memory, you’ll create a class responsible for mapping words to ids.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c10a919e0af9eb359a261031ca17b0e3/href">https://medium.com/media/c10a919e0af9eb359a261031ca17b0e3/href</a></iframe><h4>Creating a caption generator</h4><p>To generate captions, first you’ll create a caption generator. This caption generator utilizes beam search to improve the quality of sentences generated.</p><p>At each iteration, the generator passes the previous state of the LSTM (initial state is the image embedding) and previous sequence to generate the next softmax vector.</p><p>The top N most probable candidates are kept and utilized in the next inference step. This process continues until either the max sentence length is reached or all sentences have generated the end-of-sentence token.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/98ecd182d97cccc70ce92bfc7af9aefc/href">https://medium.com/media/98ecd182d97cccc70ce92bfc7af9aefc/href</a></iframe><p>Next, you’ll load the show and tell model and use it with the above caption generator to create candidate sentences. These sentences will be printed along with their log probability.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c150d15f9dd388adaafc02bb85e0ccca/href">https://medium.com/media/c150d15f9dd388adaafc02bb85e0ccca/href</a></iframe><h4>Results</h4><p>To generate captions, you’ll need to pass in one or more images to the script.</p><pre>docker run -v $PWD:/opt/app \<br>-e PYTHONPATH=$PYTHONPATH:/opt/app \<br>-it colemurray/medium-show-and-tell-caption-generator  \<br>python3 /opt/app/medium_show_and_tell_caption_generator/inference.py \<br>--model_path /opt/app/etc/show-and-tell.pb \<br>--input_files /opt/app/imgs/trading_floor.jpg \<br>--vocab_file /opt/app/etc/word_counts.txt</pre><p>You should see output:</p><pre>Captions for image trading_floor.jpg:<br> 0) a group of people sitting at tables in a room . (p=0.000306)<br> 1) a group of people sitting around a table with laptops . (p=0.000140)<br> 2) a group of people sitting at a table with laptops . (p=0.000069)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*JVTNDR601aHk7NCRILdHTQ.jpeg" /><figcaption>Generated Caption: a group of people sitting around a table with laptops</figcaption></figure><h3>Conclusion</h3><p>In this tutorial, you learned:</p><ul><li>how a convolutional neural network and LSTM can be combined to generate captions to an image</li><li>how to utilize the beam search algorithm to consider multiple captions and select the most probable sentence.</li></ul><p>Complete code <a href="https://github.com/ColeMurray/medium-show-and-tell-caption-generator">here</a>.</p><p><strong>Next Steps</strong>:</p><ul><li>Try with your own images</li><li>Read the <a href="https://arxiv.org/abs/1411.4555">Show and Tell paper</a></li><li>Create an API to serve captions</li></ul><h3>Call to Action:</h3><p>If you enjoyed this tutorial, follow and recommend!</p><p>Interested in learning more about Deep Learning / Machine Learning? Check out my other tutorials:</p><p>- <a href="https://hackernoon.com/building-a-facial-recognition-pipeline-with-deep-learning-in-tensorflow-66e7645015b8">Building a Facial Recognition Pipeline with Deep Learning in Tensorflow</a></p><p><a href="https://medium.com/p/cba6efe0acc2">- Deep Learning CNN’s in Tensorflow with GPUs</a></p><p><a href="https://medium.com/google-cloud/keras-inception-v3-on-google-compute-engine-a54918b0058">- Deep Learning with Keras on Google Compute Engine</a></p><p><a href="https://medium.com/google-cloud/recommendation-systems-with-spark-on-google-dataproc-bbb276c0dafd">- Recommendation Systems with Apache Spark on Google Compute Engine</a></p><p>Other places you can find me:</p><p>- Twitter: <a href="https://twitter.com/_ColeMurray">https://twitter.com/_ColeMurray</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a142722e9b1f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/free-code-camp/building-an-image-caption-generator-with-deep-learning-in-tensorflow-a142722e9b1f">Building an image caption generator with Deep Learning in Tensorflow</a> was originally published in <a href="https://medium.com/free-code-camp">We’ve moved to freeCodeCamp.org/news</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a Facial Recognition Pipeline with Deep Learning in Tensorflow]]></title>
            <link>https://medium.com/hackernoon/building-a-facial-recognition-pipeline-with-deep-learning-in-tensorflow-66e7645015b8?source=rss-8d62c20970c7------2</link>
            <guid isPermaLink="false">https://medium.com/p/66e7645015b8</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[facial-recognition]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[tensorflow]]></category>
            <dc:creator><![CDATA[Cole Murray]]></dc:creator>
            <pubDate>Mon, 07 Aug 2017 16:00:20 GMT</pubDate>
            <atom:updated>2019-05-22T11:10:20.127Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wh1N-kogDMaZYS17lqyqeQ.jpeg" /></figure><p>In my <a href="https://hackernoon.com/deep-learning-cnns-in-tensorflow-with-gpus-cba6efe0acc2">last tutorial</a> , you learned about convolutional neural networks and the theory behind them. In this tutorial, you’ll learn how to use a convolutional neural <a href="https://hackernoon.com/tagged/network">network</a> to perform facial recognition using Tensorflow, Dlib, and Docker.</p><h3>Overview</h3><ul><li>Introduction to Facial Recognition</li><li>Preprocessing Images using Facial Detection and Alignment</li><li>Generating Facial Embeddings in Tensorflow</li><li>Training an SVM Classifier</li></ul><h4>Prerequisites</h4><ul><li>Basic understanding of Linear Algebra</li><li>Basic understanding of Convolutional Neural Networks</li><li>Basic Tensorflow understanding</li></ul><h3><strong>Introduction to Facial Recognition Systems</strong></h3><p>Facial recognition is a biometric solution that measures unique characteristics about one’s face. Applications available today include <a href="http://www.npr.org/sections/alltechconsidered/2017/06/26/534131967/facial-recognition-may-boost-airport-security-but-raises-privacy-worries">flight checkin</a>, tagging friends and family members in photos, and <a href="https://www.theguardian.com/media/pda/2010/sep/27/advertising-billboards-facial-recognition-japan">“tailored” advertising.</a></p><p>To perform facial recognition, you’ll need a way to uniquely represent a face. In 1960, Woodrow Bledsoe used a technique involving marking the coordinates of prominent features of a face. Among these features were the location of hairline, eyes and nose.</p><p>In 2015, researchers from Google released a paper, <a href="https://arxiv.org/abs/1503.03832">FaceNet</a>, which uses a convolutional neural network relying on the image pixels as the features, rather than extracting them manually. It achieved a new record accuracy of 99.63% on the <a href="http://vis-www.cs.umass.edu/lfw/">LFW dataset</a>.</p><p><strong>FaceNet: </strong>In the FaceNet paper, a convolutional neural network architecture is proposed. For a loss function, FaceNet uses “triplet loss”. Triplet loss relies on minimizing the distance from positive examples, while maximizing the distance from negative examples.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/588/1*dYCg9TdSj4yHfwygxKcxRQ.png" /><figcaption>Triplet loss equation</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/1*gIW1Ak5KMvIDAugd3l15FA.png" /><figcaption>Triplet loss Learning</figcaption></figure><p>Conceptually, this makes sense. Faces of the same identity should appear closer to each other than faces of another identity.</p><p><strong>Vector Embeddings: </strong>For this tutorial, the important take away from the paper is the idea of representing a face as a 128-dimensional <strong>embedding</strong>. An embedding is the collective name for mapping input features to vectors. In a facial recognition system, these inputs are images containing a subject’s face, mapped to a numerical vector representation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/172/1*tCeGt4fuK_gX1fh8OSyz1Q.png" /><figcaption>Mapping input to embedding <a href="https://www.slideshare.net/BhaskarMitra3/vectorland-brief-notes-from-using-text-embeddings-for-search">source</a></figcaption></figure><p>Since these vector embeddings are represented in shared vector space, vector distance can be used to calculate the similarity between two vectors. In a facial recognition context, this can vector distance be applied to calculate how similar two faces are. Additionally, these embeddings can be used as feature inputs into a classification, clustering, or regression task.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/326/1*f1NMkaoh_SZmOP1-YKbF6A.jpeg" /><figcaption>Example of plotting embeddings in a 3D vector space</figcaption></figure><h3>Preprocessing Data using Dlib and Docker</h3><pre># Project Structure</pre><pre>├── Dockerfile<br>├── etc<br>│ ├── 20170511–185253<br>│ │ ├── 20170511–185253.pb<br>├── data<br>├── medium_facenet_tutorial<br>│ ├── align_dlib.py<br>│ ├── download_and_extract_model.py<br>│ ├── __init__.py<br>│ ├── lfw_input.py<br>│ ├── preprocess.py<br>│ ├── shape_predictor_68_face_landmarks.dat<br>│ └── train_classifier.py<br>├── requirements.txt</pre><h4><strong>Preparing the Data</strong></h4><p>You’ll use the LFW (Labeled Faces in the Wild) dataset as training data. The directory is structured as seen below. You can replace this with your dataset by following the same structure.</p><pre># Download lfw dataset<br>$ curl -O <a href="http://vis-www.cs.umass.edu/lfw/lfw.tgz">http://vis-www.cs.umass.edu/lfw/lfw.tgz</a> # 177MB<br>$ tar -xzvf lfw.tgz</pre><pre># Directory Structure<br># ├── Tyra_Banks<br># │ ├── Tyra_Banks_0001.jpg<br># │ └── Tyra_Banks_0002.jpg<br># ├── Tyron_Garner<br># │ ├── Tyron_Garner_0001.jpg<br># │ └── Tyron_Garner_0002.jpg</pre><h4><strong>Preprocessing</strong></h4><p>Below, you’ll pre-process the images before passing them into the FaceNet model. Image pre-processing in a facial recognition context typically solves a few problems. These problems range from lighting differences, occlusion, alignment, segmentation. Below, you’ll address segmentation and alignment.</p><p>First, you’ll solve the segmentation problem by finding the largest face in an image. This is useful as our training data does not have to be cropped for a face ahead of time.</p><p>Second, you’ll solve alignment. In photographs, it is common for a face to not be perfectly center aligned with the image. To standardize input, you’ll apply a transform to center all images based on the location of eyes and bottom lip.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*W-kzqrbo-zwIdxLgwZPHHg.jpeg" /><figcaption>Segment, align, and crop</figcaption></figure><p><strong>Environment Setup</strong></p><p>Here, you’ll use docker to install tensorflow, opencv, and Dlib. Dlib provides a library that can be used for facial detection and alignment. These libraries can be a bit difficult to install, so you’ll use Docker for the install.</p><p>Docker is a container platform that simplifies deployment. It solves the problem of installing software dependencies onto different server environments. If you are new to docker, you can read more <a href="https://www.docker.com/">here</a>. To install docker, run</p><pre>curl <a href="https://get.docker.com/">https://get.docker.com</a> | sh</pre><p>After installing docker, you’ll create two files. A <strong>requirements.txt </strong>for the python dependencies and a <strong>Dockerfile </strong>to create your docker environment.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c48b7c13d29db697efc7858a66e70b35/href">https://medium.com/media/c48b7c13d29db697efc7858a66e70b35/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b10b11a67c128b353a50971e12f5a50/href">https://medium.com/media/5b10b11a67c128b353a50971e12f5a50/href</a></iframe><p>To build this image, run:</p><pre>$ docker build -t colemurray/medium-facenet-tutorial -f Dockerfile .</pre><pre># This can take several minutes depending on your hardware<br># On MBP, ~ 25mins<br># Image can be pulled from dockerhub below</pre><p>If you would like to avoid building from source, the image can be pulled from dockerhub using:</p><pre>docker pull colemurray/medium-facenet-tutorial # Recommended</pre><pre># A GPU supported environment can be found here<br># nvidia-docker pull colemurray/medium-facenet-tutorial:latest-gpu</pre><h4>Detect, Crop &amp; Align with Dlib</h4><p>After creating your environment, you can begin preprocessing.</p><p>First download dlib’s face landmark predictor.</p><pre>$ curl -O <a href="http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2">http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2</a><br>$ bzip2 -d shape_predictor_68_face_landmarks.dat.bz2</pre><p>You’ll use this face landmark predictor to find the location of the inner eyes and bottom lips of a face in an image. These coordinates will be used to center align the image.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d04e3dbfda31ea1531d900ed3e1d0acd/href">https://medium.com/media/d04e3dbfda31ea1531d900ed3e1d0acd/href</a></iframe><p>This file, sourced from CMU, provides methods for detecting a face in an image, finding facial landmarks, and alignment given these landmarks.</p><p>Next, you’ll create a preprocessor for your dataset. This file will read each image into memory, attempt to find the largest face, center align, and write the file to output. If a face cannot be found in the image, logging will be displayed to console with the filename.</p><p>As each image can be processed independently, python’s multiprocessing is used to process an image on each available cpu core.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a97cb43995b981b13b1be8ea469c9255/href">https://medium.com/media/a97cb43995b981b13b1be8ea469c9255/href</a></iframe><p><strong>Getting Results</strong></p><p>Now that you’ve created a pipeline, time to get results. As the script supports parallelism, you will see increased performance by running with multiple cores. You’ll need to run the preprocessor in the docker environment to have access to the installed libraries.</p><p>Below, you’ll mount your project directory as a volume inside the docker container and run the preprocessing script on your input data. The results will be written to a directory specified with command line arguments.</p><pre>$ docker run -v $PWD:/medium-facenet-tutorial \<br>-e PYTHONPATH=$PYTHONPATH:/medium-facenet-tutorial \<br>-it colemurray/medium-facenet-tutorial python3 /medium-facenet-tutorial/medium_facenet_tutorial/preprocess.py \<br>--input-dir /medium-facenet-tutorial/<strong>data</strong> \<br>--output-dir /medium-facenet-tutorial/output/intermediate \<br>--crop-dim 180</pre><blockquote>Code up to this point can be found <a href="https://github.com/ColeMurray/medium-facenet-tutorial/tree/add_alignment">here</a></blockquote><h4><strong>Review</strong></h4><p>Using Dlib, you detected the largest face in an image and aligned the center of the face by the inner eyes and bottom lip. This alignment is a method for standardizing each image for use as feature input.</p><h3><strong>Creating Embeddings in Tensorflow</strong></h3><p>Now that you’ve preprocessed the data, you’ll generate vector embeddings of each identity. These embeddings can then be used as input to a classification, regression or clustering task.</p><h4><strong>Download Weights</strong></h4><p>You’ll use the Inception Resnet V1 as your convolutional neural network. First, create a file to download the weights to the model.</p><p>By using pre-trained weights, you are able to apply <a href="https://cs231n.github.io/transfer-learning/">transfer learning</a> to a new dataset, in this tutorial the LFW dataset:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6f433266c294bea5a84f425fb005c949/href">https://medium.com/media/6f433266c294bea5a84f425fb005c949/href</a></iframe><pre>$ docker run -v $PWD:/medium-facenet-tutorial \<br>-e PYTHONPATH=$PYTHONPATH:/medium-facenet-tutorial \<br>-it colemurray/medium-facenet-tutorial python3 /medium-facenet-tutorial/medium_facenet_tutorial/download_and_extract_model.py \<br>--model-dir /medium-facenet-tutorial/etc</pre><h4><strong>Load Embeddings</strong></h4><p>Below, you’ll utilize Tensorflow’s queue api to load the preprocessed images in parallel. By using queues, images can be loaded in parallel using multi-threading. When using a GPU, this allows image preprocessing to be performed on CPU, while matrix multiplication is performed on GPU.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/14722632330bb66f6bdc8197f0df81a0/href">https://medium.com/media/14722632330bb66f6bdc8197f0df81a0/href</a></iframe><h4>Train a Classifier</h4><p>With the input queue squared away, you’ll move on to creating the embeddings.</p><p>First, you’ll load the images from the queue you created. While training, you’ll apply preprocessing to the image. This preprocessing will add random transformations to the image, creating more images to train on.</p><p>These images will be fed in a batch size of 128 into the model. This model will return a 128 dimensional embedding for each image, returning a 128 x 128 matrix for each batch.</p><p>After these embeddings are created, you’ll use them as feature inputs into a scikit-learn’s SVM classifier to train on each identity. Identities with less than 10 images will be dropped. This parameter is tunable from command-line.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/de6ece88e76340cd8f1d010e71033b34/href">https://medium.com/media/de6ece88e76340cd8f1d010e71033b34/href</a></iframe><pre>$ docker run -v $PWD:/medium-facenet-tutorial \<br>-e PYTHONPATH=$PYTHONPATH:/medium-facenet-tutorial \<br>-it colemurray/medium-facenet-tutorial \<br>python3 /medium-facenet-tutorial/medium_facenet_tutorial/train_classifier.py \<br>--input-dir /medium-facenet-tutorial/output/intermediate \<br>--model-path /medium-facenet-tutorial/etc/20170511-185253/20170511-185253.pb \<br>--classifier-path /medium-facenet-tutorial/output/classifier.pkl \<br>--num-threads 16 \<br>--num-epochs 25 \<br>--min-num-images-per-class 10 \<br>--is-train </pre><pre># ~16 mins to complete on MBP</pre><p><strong>Evaluating the Results</strong></p><p>Now that you’ve trained the classifier, you’ll feed it new images it has not trained on. You’ll remove the is_train flag from the previous command to evaluate your results.</p><pre>docker run -v $PWD:/$(basename $PWD) \<br>-e PYTHONPATH=$PYTHONPATH:/medium-facenet-tutorial \<br>-it colemurray/medium-facenet-tutorial \<br>python3 /medium-facenet-tutorial/medium_facenet_tutorial/train_classifier.py \<br>--input-dir /medium-facenet-tutorial/output/intermediate \<br>--model-path /medium-facenet-tutorial/etc/20170511-185253/20170511-185253.pb \<br>--classifier-path /medium-facenet-tutorial/output/classifier.pkl \<br>--num-threads 16 \<br>--num-epochs 5 \<br>--min-num-images-per-class 10</pre><p>After inference is on each image is complete, you’ll see results printed to console. At 5 epochs, you’ll see ~85.0% accuracy. Training @ 25 epochs gave results:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/1*75xOtN-cLgAFeNSt6E7stg.png" /><figcaption>90.8% @ 25 epochs</figcaption></figure><h3>Conclusion</h3><p>In this tutorial, you learned about the history of machine <a href="https://hackernoon.com/tagged/learning">learning</a> and how to implement a state of the art pipeline. You utilized docker to manage your library dependencies, offering a consistent environment that is platform agnostic. You used Dlib for preprocessing and Tensorflow + Scikit-learn for training a classifier capable of predicting an identity based on an image.</p><p>Complete Code Here:</p><p><a href="https://github.com/ColeMurray/medium-facenet-tutorial">ColeMurray/medium-facenet-tutorial</a></p><p><strong>Next Steps:</strong></p><ul><li>Test on your own dataset!</li><li>Experiment with different hyper parameters</li><li>Train on other labels such as gender or age</li><li>Implement a clustering algorithm to group similar faces</li></ul><h3>Call to Action:</h3><blockquote>If you enjoyed this tutorial, follow and recommend!</blockquote><blockquote>Interested in learning more about Deep Learning / Machine Learning? Check out my other tutorials:</blockquote><blockquote><a href="https://medium.com/p/cba6efe0acc2">- Deep Learning CNN’s in Tensorflow with GPUs</a></blockquote><blockquote><a href="https://medium.com/google-cloud/keras-inception-v3-on-google-compute-engine-a54918b0058">- Deep Learning with Keras on Google Compute Engine</a></blockquote><blockquote><a href="https://medium.com/google-cloud/recommendation-systems-with-spark-on-google-dataproc-bbb276c0dafd">- Recommendation Systems with Apache Spark on Google Compute Engine</a></blockquote><blockquote>Other places you can find me:</blockquote><blockquote>- Twitter: <a href="https://twitter.com/_ColeMurray">https://twitter.com/_ColeMurray</a></blockquote><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2Fdde502%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2Fdde502%2F&amp;image=https%3A%2F%2Fucarecdn.com%2F57662ddc-da7c-407b-afcb-cb45184b2705%2F&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/d25dd15e8727342107fbe0b6d67b030e/href">https://medium.com/media/d25dd15e8727342107fbe0b6d67b030e/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=66e7645015b8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/building-a-facial-recognition-pipeline-with-deep-learning-in-tensorflow-66e7645015b8">Building a Facial Recognition Pipeline with Deep Learning in Tensorflow</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>