<?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 Willis Zhang on Medium]]></title>
        <description><![CDATA[Stories by Willis Zhang on Medium]]></description>
        <link>https://medium.com/@williszhang?source=rss-399c0f7a30c8------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*4v7FCGN5E7sl0u-t88HA6g.jpeg</url>
            <title>Stories by Willis Zhang on Medium</title>
            <link>https://medium.com/@williszhang?source=rss-399c0f7a30c8------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 23:42:30 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@williszhang/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[See you in the neighborhood: using Generative AI to support housing assistance programs]]></title>
            <link>https://medium.com/google-cloud/see-you-in-the-neighborhood-using-generative-ai-to-support-housing-assistance-programs-e0f35598eef3?source=rss-399c0f7a30c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/e0f35598eef3</guid>
            <category><![CDATA[bigquery]]></category>
            <category><![CDATA[gemini]]></category>
            <category><![CDATA[generative-ai]]></category>
            <category><![CDATA[data]]></category>
            <category><![CDATA[google-cloud-platform]]></category>
            <dc:creator><![CDATA[Willis Zhang]]></dc:creator>
            <pubDate>Mon, 18 Mar 2024 14:58:27 GMT</pubDate>
            <atom:updated>2024-03-20T10:17:47.832Z</atom:updated>
            <content:encoded><![CDATA[<h3>See you in the neighborhood: using Gemini to support housing assistance programs</h3><p><em>This demo was originally created by </em><a href="https://medium.com/u/24c4b96c21c5"><em>G. Hussain Chinoy</em></a><em> and reworked to fit a housing use case.</em></p><p>Local governments are responsible for providing assistance to those in need but often lack the resources to do so at scale. As a result, many people who are eligible for assistance programs do not receive them quickly enough. One way to address this problem is to use data analytics to identify those who are most likely to need assistance and then target them with outreach efforts.</p><p>Using housing as an example, we will demonstrate step-by-step how to use <a href="https://cloud.google.com/bigquery">BigQuery</a> to understand our applicant population, then use <a href="https://cloud.google.com/vertex-ai?hl=en">Generative AI in Vertex AI</a> to cater assistance programs to the right people.</p><h3><strong>Segment our population into cohorts</strong></h3><p>First, we will use ML and <a href="https://cloud.google.com/datasets">public datasets</a> in BigQuery to segment different cohorts of underserved populations. The following SQL query creates a <a href="https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-create-kmeans">k-means model</a> that will group county populations in the United States into 3 general clusters. You can copy and paste the query directly into the <a href="https://console.cloud.google.com/bigquery?_ga=2.61904235.699649399.1702343748-1775525831.1702327339">BigQuery UI</a>.</p><pre>CREATE OR REPLACE MODEL `&lt;dataset-name&gt;.housing_pool`<br>OPTIONS<br> ( MODEL_TYPE=&#39;KMEANS&#39;,<br>   NUM_CLUSTERS=3 ) AS<br>  <br>WITH<br> acs_2017 AS (<br> SELECT<br>   geo_id,<br>   rent_over_50_percent + rent_40_to_50_percent + rent_35_to_40_percent AS rent_over_35_percent,<br>   housing_units_renter_occupied AS rental_units,<br>   commuters_by_public_transportation/total_pop AS public_transit,<br>   vacant_housing_units/total_pop AS vacant_units,<br>   families_with_young_children/total_pop AS young_families,<br> FROM<br>   `bigquery-public-data.census_bureau_acs.county_2017_5yr`<br>   WHERE housing_units_renter_occupied &lt;&gt; 0),<br><br><br>LIHTC_Units AS (<br> SELECT<br>   SUM(n_units) AS total_LIHTC_units,<br>   SUBSTR (fips2010,0,5) AS shortFIPS<br> FROM<br>   `bigquery-public-data.sdoh_hud_housing.2017_lihtc_database_hud`<br> WHERE n_units &lt;&gt; 0<br> GROUP BY shortFIPS ),<br> join_tbl AS (<br> SELECT<br>   ML.MIN_MAX_SCALER(ROUND((rent_over_35_percent/rental_units)/(total_LIHTC_units/rental_units),3)) OVER() AS rent_burden,<br>   ML.MIN_MAX_SCALER(ROUND(public_transit/(total_LIHTC_units/rental_units),3)) OVER() AS public_transit,<br>   ML.MIN_MAX_SCALER(ROUND(vacant_units/(total_LIHTC_units/rental_units),3)) OVER() AS vacant_units,<br>   ML.MIN_MAX_SCALER(ROUND(young_families/(total_LIHTC_units/rental_units),3)) OVER() AS young_families<br> FROM acs_2017<br> JOIN LIHTC_Units ON acs_2017.geo_id = LIHTC_Units.shortFIPS )<br><br><br>SELECT * FROM join_tbl</pre><p>Here are some details about the query:</p><ul><li>It joins data from the Census Bureau’s American Community Survey (ACS) and from the Department of Housing and Urban Development (HUD) Low-Income Housing Tax Credit (LIHTC) program</li><li>We look at the population who pay over 35% of their income towards rent</li><li>Other inputs include the population that commutes using public transportation, vacant housing units, and families with young children</li><li>The inputs are normalized based on the total population</li><li>We further factor <em>total_LIHTC_units</em> into our features in order to heavily weigh populations that have less LIHTC coverage</li><li>Finally, we use <em>MIN_MAX_SCALER</em> as a helpful ML preprocessing function to scale our units between 0 and 1</li></ul><p>After a minute of running, the query to create the model should be done. Click <strong>Go To Model</strong>, and then click the <strong>Evaluation</strong> tab to see numeric breakdowns of our clusters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oxkqj82V3Y3U0td9" /></figure><p>You can now use this model to see which cluster your county belongs to (<a href="https://transition.fcc.gov/oet/info/maps/census/fips/fips.txt">here is a helpful reference</a> from the Federal Communications Commission).</p><h3><strong>Understand our results and get recommendations</strong></h3><p>When looking at the blend of socioeconomics for each cohort, it may be difficult to find a concise way to describe each of them. This only gets harder as we increase the number of features. <strong>Generative AI can assist in synthesizing the main themes of our data</strong> and presenting it back in a way that can “prompt” follow up action.</p><p>Save the image above of the evaluation breakdown. We’ll use it in our prompt to the <a href="https://console.cloud.google.com/vertex-ai/generative/multimodal">Gemini Multimodal model in Vertex AI</a>: inside your project, click “Insert Media” to insert the image, then paste the following prompt:</p><pre>{Mission}<br>You help government officials market housing <br>assistance programs. You customize assistance <br>programs to the needs of specific populations.<br><br>{Instructions}<br>Given the following population clusters and their <br>socioeconomic makeup shown in the picture, explain <br>if the cluster is suitable for housing assistance. <br>Then for each of the clusters suitable for <br>assistance, come up with a brand persona and <br>campaign title based on their distinct attributes, <br>and explain what would be the appropriate next <br>step for each of those clusters.</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ihBzeje8Hu94pg6f" /></figure><p>The parameters used were:</p><pre>   Temperature: 0.1,<br>   Token limit: 1389,<br>   Top-K: 33,<br>   Top-P: 0.77</pre><p>After pressing “Submit,” the result may be similar to this:</p><pre><strong>Cluster 1: Young Families with Low Rent Burden</strong><br>  - Suitable for assistance: No<br>  - The rent burden is very low, indicating that housing <br>    costs are not a significant challenge for this cluster. <br>  - The public transit usage is also low, suggesting that <br>    they may have access to other means of transportation. <br>  - The vacancy rate is relatively high, which means there <br>    may be sufficient housing options available without <br>    the need for assistance.<br><br><strong>Cluster 2: Young Families with Moderate Rent Burden</strong><br>  - Suitable for assistance: Yes<br>  - The rent burden is higher than Cluster 1, indicating <br>    that housing costs may be a challenge for some <br>    families in this cluster.<br>  - The public transit usage is slightly higher, <br>    suggesting that they may rely on public transportation <br>    for commuting.<br>  - The vacancy rate is higher than Cluster 1, but still <br>    relatively low, indicating that there may be some <br>    competition for affordable housing.<br><br><strong>Brand persona:</strong> Struggling Young Family <br><strong>Title label:</strong> &quot;Helping Young Families Thrive: Affordable <br>    Housing Solutions&quot; <br><strong>Next step:</strong> Provide information about affordable housing <br>    options, rental assistance programs, and financial <br>    counseling services.<br><br><strong>Cluster 3: Young Families with Moderate Rent Burden and <br>    High Public Transit Usage<br>  </strong>-<strong> </strong>Suitable for assistance: Yes<br>  - The rent burden is similar to Cluster 2, but the <br>    public transit usage is significantly higher, <br>    indicating that they heavily rely on public <br>    transportation for commuting.<br>  - The vacancy rate is lower than Cluster 2, suggesting <br>    that there may be a shortage of affordable housing <br>    options in this area.<br><br><strong>Brand persona:</strong> Commuting Young Family <br><strong>Title label:</strong> &quot;Affordable Housing for Commuters: Making <br>    Transit-Oriented Living a Reality&quot; <br><strong>Next step:</strong> Provide information about affordable housing <br>    options near public transit hubs, transportation <br>    subsidies, and car-sharing programs.</pre><p>This response helps us to de-prioritize cohorts that align with cluster 1 while shoring up the specific needs of clusters 2 and 3. Feel free to dial the temperature and other parameters as you see fit and provide more agency-specific guidelines on scoring applicant need.</p><h3><strong>Next steps</strong></h3><p>This introductory level use case provides a blueprint for building your own models using these queries and prompts as an initial template. Where you can go from here:</p><ul><li>The <a href="http://console.cloud.google.com/marketplace/product/united-states-census-bureau/acs">ACS dataset</a> can get more granular, up to the block group and census tract level, but providing your agency’s historical applicant data would have the greatest impact on a model’s utility</li><li>BigQuery and Vertex AI provide many more prediction services, such as creating a <a href="https://cloud.google.com/bigquery/docs/bigqueryml-mf-implicit-tutorial#run_the_create_model_query">recommendation engine</a> that could assist applicants with the best resources or <a href="https://cloud.google.com/bigquery/docs/understand-text">analyzing sentiment</a> on tickets or survey responses to track emerging areas of concern</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e0f35598eef3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/google-cloud/see-you-in-the-neighborhood-using-generative-ai-to-support-housing-assistance-programs-e0f35598eef3">See you in the neighborhood: using Generative AI to support housing assistance programs</a> was originally published in <a href="https://medium.com/google-cloud">Google Cloud - Community</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[BigQuery GIS + ML on government open data]]></title>
            <link>https://medium.com/@williszhang/bigquery-gis-ml-on-government-open-data-2605ed9d2e8?source=rss-399c0f7a30c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/2605ed9d2e8</guid>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[gis]]></category>
            <category><![CDATA[bigquery]]></category>
            <category><![CDATA[gcp]]></category>
            <dc:creator><![CDATA[Willis Zhang]]></dc:creator>
            <pubDate>Thu, 30 May 2019 15:54:06 GMT</pubDate>
            <atom:updated>2019-07-18T16:44:20.294Z</atom:updated>
            <content:encoded><![CDATA[<h4>Use BigQuery to visualize, test, and predict citizen hypotheses using government open data.</h4><p>I’ve been having too much fun mashing together whatever public datasets I can get my hands on, with <a href="https://cloud.google.com/bigquery/">BigQuery</a> being my one-stop shop for super quick analytics, machine learning, and GIS visualization.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ei9K8fjSgv7_Ib7o5i84Ng.gif" /><figcaption>Example BQ Geo Viz query on NYC bike shares</figcaption></figure><p>Putting on my citizen data scientist hat, the hypothesis I wanted to test was: “<strong>Does higher rent lead to more housing code violations?</strong>”</p><p>Here, I used rent as a proxy for cost of living, where a higher cost of living may overburden owners and prevent them from keeping their properties up to code. I focused my initial study area to Montgomery County, MD in the DC suburbs. Here were the steps I took:</p><ol><li><strong>Prep and load the data </strong>(boring but Dataprep makes it fun)</li></ol><p>Rental info <a href="https://stat.montgomerycountymd.gov/dataset/DHCA-Rental-Survey-Results-2018/5k4y-abij">here</a> and code violation data <a href="https://data.montgomerycountymd.gov/Consumer-Housing/Housing-Code-Violations/k9nj-z35d">here</a>. Just export and download the CSVs.</p><p>Now set up your GCP environment: go to the <a href="http://console.cloud.google.com/">console</a> and create a project with a billing account if you haven’t already (we should be well under the $300 in free trial credits). You may be enabling APIs along the way.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/200/1*Y7r9Ri9lNq-gi7PWTjgUNQ.png" /></figure><p>We’re actually going to clean our data in <a href="https://cloud.google.com/dataprep/">Dataprep</a> first. Find Dataprep on the console left-side menu and click through the agreements.</p><p>Let’s start by wrangling the DHCA Rental Survey data. Import the CSV from your local machine or <a href="https://cloud.google.com/storage/">Cloud Storage</a>, then create a new recipe.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_dMxxAOMY70-tUg1yfHCDw.png" /><figcaption>We’ll end up creating two flows for each CSV</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/639/0*Dxoy_h0RWAyy-lH4" /><figcaption>Dataprep: point-and-click ETL please because I don’t want to code</figcaption></figure><p>Here’s the recipe I used for the DHCA Rental Survey, essentially extracting the zip code, converting it into a string, and deleting missing rows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/604/1*c0NMb-dbp_2xXQKbhg4FcQ.png" /><figcaption>Wrangle recipe in natural language, with wrangle file on the right</figcaption></figure><pre>extractpositions col: {Facility Address} type: last count: 6<br>rename type: manual mapping: [{right_Facility Address},&#39;zipcode&#39;]<br>textformat col: zipcode type: trimwhitespace<br>textformat col: {Facility Name} type: trimwhitespace<br>textformat col: {Facility Name} type: trimquotes<br>filter type: custom rowType: single row: ISMISMATCHED(zipcode, [&#39;Zipcode&#39;]) action: Delete<br>drop col: {Facility Address} action: Drop<br>drop col: {Average Rent  2015} action: Drop<br>drop col: {Average Rent  2016} action: Drop<br>drop col: {Average Rent  2017} action: Drop<br>drop col: {Average Rent  2018} action: Drop<br>drop col: {Bedroom Types} action: Drop<br>textformat col: {Facility Name} type: trimwhitespace<br>settype col: zipcode type: String</pre><p>Click “Run Job” and specify the following settings to keep it simple: “no compression, single file, with headers, with quotes, with delimiter: ,”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/250/1*yHPhE_jN2iVN-7B43iJEGA.png" /><figcaption>Apache Beam without typing any JavaScript</figcaption></figure><p>You can actually look at the Dataflow (Apache Beam) job if you’re curious about the mapreduce steps.</p><p>Follow the same steps for the Code Violations CSV. Wrangle recipe below. MoCo will acknowledge its violations data is a little messy, so I deleted a lot of columns where there were missing values.</p><pre>drop col: Latitude action: Drop<br>drop col: Longitude action: Drop<br>drop col: {:<a href="http://twitter.com/computed_region_a9cs">@computed_region_a9cs</a>_3ed7} action: Drop<br>drop col: {:<a href="http://twitter.com/computed_region_r648">@computed_region_r648</a>_kzwt} action: Drop<br>settype col: {Zip Code} type: String<br>drop col: {Date Closed} action: Drop<br>drop col: {Zip Codes} action: Drop<br>drop col: {Council Districts} action: Drop<br>drop col: Councils action: Drop<br>drop col: Communities action: Drop<br>drop col: Municipalities action: Drop<br>drop col: {Unit Number} action: Drop<br>drop col: {Service Request Number} action: Drop<br>drop col: {Service Request Created Date} action: Drop<br>drop col: {Service Request Closed Time} action: Drop<br>drop col: {Service Request Status} action: Drop<br>drop col: Corrected action: Drop<br>drop col: {Inspection Date} action: Drop<br>drop col: {Location Description} action: Drop<br>drop col: {Code Reference} action: Drop<br>drop col: Disposition action: Drop<br>drop col: Location action: Drop<br>drop col: {Date Assigned}: Drop</pre><p>Now for the main attraction: from the console, go to BigQuery to start loading our tables.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fv3CfHEpOlc8hbaq244H8g.png" /></figure><p>Create a dataset where you’ll store tables. I’m calling mine “moco_rent_violations.”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fjcaL42NWfytkyx9rPmvKw.png" /></figure><p>Then create a new table.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D6T_HGdm9zVfIH7avmKa1w.png" /></figure><p>I’ll name this table “code_violations” and find the source CSV from the Dataprep job output in Google Cloud Storage stored in bucket:</p><pre>gs://dataprep-staging-*/&lt;USER&gt;/jobrun/</pre><p>Instead of auto detecting the schema, I’ll actually be prescriptive and “Edit as text,” making all my fields type STRING:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/60831d01a888633c62b9c0f9f67778f5/href">https://medium.com/media/60831d01a888633c62b9c0f9f67778f5/href</a></iframe><p>Then click “Create table”! You can see successful (or unsuccessful) job loads in Job history.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GeeCC3R0Jx0vv89pQjFdBg.png" /></figure><p>We’ll similarly load our DHCA Rental Survey table and call it “rental”. Schema below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d72d79c8a3d354ebd3bd26c3742bfadf/href">https://medium.com/media/d72d79c8a3d354ebd3bd26c3742bfadf/href</a></iframe><p>Yay! All our tables are loaded.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/946/1*fUXvOuDW7rrcu0OYYY38uQ.png" /></figure><p><strong>2. Instead of nested joins, create lots of views</strong></p><p>I’m going to now join these tables on zip code and selecting number of violations and the associated rent difference in that zip code. Enter the following in the BigQuery Query Editor:</p><pre>SELECT <br>zipcode, <br>count(DISTINCT Violation_ID) as violations,<br>AVG(Average_Rent_Percent_Difference_From_Previous_Year) as rent_diff <br>FROM <br>`&lt;PROJECT-ID&gt;.moco_rent_violations.code_violations`<br>JOIN<br>`&lt;PROJECT-ID&gt;.moco_rent_violations.rental`<br>ON<br>Zip_Code = zipcode<br>GROUP BY<br>zipcode</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PUkbqjdZ2-jKB03cuz758Q.png" /><figcaption>All the green check marks mean our query is good to go. Feel free to “Save query” for future reference.</figcaption></figure><p>Now to get ready for the next step of visualization, I want to join GIS polygons in this query (with the <a href="https://www.google.com/search?q=zcta+bigquery&amp;rlz=1CAVNXA_enUS785US785&amp;oq=zcta&amp;aqs=chrome.1.69i59l2j0j69i60l2j0.2374j0j4&amp;sourceid=chrome&amp;ie=UTF-8">ZCTA dataset</a> in GCP marketplace). If you haven’t gathered from my Dataprep run-through, I really don’t like long code, so if I can save myself typing a couple nested joins then that’s a win.</p><p>I can do this by saving these aggregated query results as a “View” and essentially interact with it as a table, but should the underlying data from the original tables change, the View would surface these updates in its aggregation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iYIOyitmS4Ua0_YNyXmYmQ.png" /></figure><p>Now I can join this violations_rental view with zip code polygons:</p><pre>SELECT <br>violations_rental.zipcode,<br>violations,<br>rent_diff,<br>zip_area.zcta_geom AS zipcode_polygon,<br>ST_GeogPoint(int_point_lon,int_point_lat) AS lat_lon<br>FROM <br>`&lt;PROJECT-ID&gt;.moco_rent_violations.violations_rental` AS violations_rental<br>JOIN<br>`bigquery-public-data.geo_us_boundaries.us_zip_codes` AS zip_area<br>ON<br>  zip_area.zip_code = violations_rental.zipcode<br>WHERE<br>  county LIKE &#39;%Montgomery%&#39;<br>  AND state_name = &#39;Maryland&#39;<br>ORDER BY<br>rent_diff DESC</pre><p>Save the results as a View “violations_rental_zip.”</p><p><strong>3. Visualize the situation today</strong></p><p>Follow the instructions from the <a href="https://www.google.com/search?q=zcta+bigquery&amp;rlz=1CAVNXA_enUS785US785&amp;oq=zcta&amp;aqs=chrome.1.69i59l2j0j69i60l2j0.2374j0j4&amp;sourceid=chrome&amp;ie=UTF-8">ZCTA dataset</a> to get your project whitelisted to start using <a href="https://bigquerygeoviz.appspot.com/">BigQuery Geo Viz</a>.</p><p>Once whitelisted, paste the last query above in “1. Select data” then press “Run.” After processing, click “See results” to move to “2. Define columns,” and select “lat_lon” as the Geometry column.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GO2wfCX5QtAZJyF0BdKbig.png" /></figure><p>Click “Add styles” to move to “3. Style.”</p><p>As an example, for fillColor, we’ll color as a Data-driven Function “linear” on Field “rent_diff.” You can then toggle the levels of coloring based on rent difference percentage.</p><p>For circleRadius, we’ll have a Data-driven Function “linear” on Field “violations” and set the circle radius levels.</p><p>If successful, we should have a circle plot of rent increases based on color and size based on number of violations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fRthWdH1Kob0iHltYJvVHw.png" /></figure><p><strong>4. Create, evaluate, and predict with ML</strong></p><p>On first look, there doesn’t seem to be an overt correlation. But we can quantify correlation or lack thereof with linear regression. So let’s build an ML model using SQL! It’s easy.</p><p>DISCLAIMER: this is for demonstration purposes, as the number of samples (28) is too aggregated and ideally we would have data more local than zip code. For the model, I found zip codes 20905 (Colesville) and 20871 (Clarksburg) to be <a href="https://www.quora.com/How-do-I-find-outliers-in-my-Google-Sheet">outliers</a> based on rent percentages so we’ll exclude them. This is the “query” to create our ML linear regression model:</p><pre>CREATE OR REPLACE MODEL `moco_rent_violations.rent_violations_ML`<br>OPTIONS(model_type=&#39;linear_reg&#39;) AS<br>SELECT <br>violations as label, <br>rent_diff <br>FROM `&lt;PROJECT-ID&gt;.moco_rent_violations.violations_rental_zip`<br>WHERE<br>zipcode != &#39;20905&#39; <br>AND zipcode != &#39;20871&#39;</pre><p>In less than a minute, we’ll have a SQL table that is actually an ML model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v9ZL0dBPJ8wWeB0C_GgPLg.png" /></figure><p>How good is it? Let’s evaluate using this query:</p><pre>WITH eval_table AS (<br>SELECT violations as label, <br>rent_diff <br>FROM `&lt;PROJECT-ID&gt;.moco_rent_violations.violations_rental`)<br>SELECT<br>*<br>FROM<br>  ML.EVALUATE(MODEL moco_rent_violations.rent_violations_ML,<br>    TABLE eval_table)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qLSa74PMdvhuKgc4-yAg9w.png" /><figcaption>To better understand the statistical results, look at this <a href="https://medium.com/eliiza-ai/introduction-to-linear-regression-with-bigquery-ml-b62d134e0c18">intro article</a></figcaption></figure><p>Seems all over. We could probably delete violations outliers as well to decrease mean_absolute_error, but we’d really have too few data. We’ll continue though for demonstration.</p><p>Let’s do a hypothetical prediction with this model! We’ll SELECT zip codes with their rent_diff numbers and use that to <strong>predict the hypothetical number of code violations for a given rent increase</strong>.</p><pre>WITH pred_table AS (<br>SELECT <br>ST_GeogFromText(zipcode_polygon) as zip_polygon,<br>rent_diff as rent_diff <br>FROM `&lt;PROJECT-ID&gt;.moco_rent_violations.violations_rental_zip`<br>Where<br>zipcode != &#39;20905&#39;<br>and zipcode != &#39;20871&#39;)<br>SELECT<br>*<br>FROM<br>  ML.PREDICT(MODEL moco_rent_violations.rent_violations_ML,<br>    TABLE pred_table)<br>Order by rent_diff asc</pre><p>Alrighty then. But let’s go one step further and visualize this. As in, <strong>visualize this ML model</strong>. Paste this query into BigQuery Geo Viz, except this time, make the Geometry column “zip_polygon.”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Mod25p4rirD7C9gOypKVUw.gif" /><figcaption>Satisfying</figcaption></figure><p>Click on one of the zip codes. In the example below, the model is saying for a 1.8% increase in rent, we can expect around 6,500 code violations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5SQCDDmntM4643-OM5rNtQ.png" /></figure><p><strong>Conclusion: </strong>there are probably <a href="https://www.researchgate.net/post/What_is_the_accepted_range_for_the_R_square_in_social_studies_please_would_you_provide_your_answer_with_reference">a lot of other factors at play</a>, but this is a super easy, <strong>fast</strong>, and economical first step to visually gain an awareness. This entire process has run me up 25 cents in expenses including failures and missteps. None of this requires a PhD or computer science background, and given more data, we can create a full Tensorflow model using <a href="https://cloud.google.com/automl-tables/">AutoML tables</a>, which is literally point-and-click. Until next time.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2605ed9d2e8" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>